Currently, the only inhabitants on Mars are robots. Every time we explore a new part of our solar system, whether it be to Europa to search for life, or to an asteroid to mine it for its resources, we will be sending a robot first. It's extremely important to know every intricate detail, especially when you're 33,926,867.096 miles from home.
• Solder the wires onto the motor prongs before attaching the motors to the chassis.
• Solder one end of the male to male jumper wires to each end of the metalic prongs connected on the DC motors, the other end of the wire will be plugged into a breadboard later. If you don't know how to solder, I recommend watching a couple videos like this one on YouTube first.
• When attaching the motors to the chassis, make sure that the motors are screwed on with the wires facing inward and with the axles attached! Then go ahead and screw on the top piece.
• Now add your tires.
• Carefully pull the left wires upward through the top chassis, then repeating again for the right wires, making sure to keep the wires on the left side and right side separated.
• Place the breadboard on the chassis in a location that will allow you to connect the DC motor wires on easily.
• Add the L293D chips to the breadboard as seen below. The yellow lines represent the top DC wires, and the green lines represent the wires underneath the top wires. *The top 2 motors in the diagram represent the front motors of the vehicle, and the bottom motors represent the back motors of the vehicle.
• You can read more about the L293D chip and what it does here in the Texas Instruments documentation.
"The L293 and L293D are quadruple high-current half-H drivers. These devices are designed to drive a wide arrayof inductive loads such as relays, solenoids, DC and bipolar stepping motors, as well as other high-current and high-voltage loads. All inputs are TTL compatible and tolerant up to 7 V.
Each output is a complete totem-pole drive circuit, with a Darlington transistor sink and a pseudo-Darlington source. Drivers are enabled in pairs, with drivers 1 and 2 enabled by 1,2EN and drivers 3 and 4 enabled by 3,4EN. When an enable input is high, the associated drivers are enabled, and their outputs are active and in phase with their inputs. When the enable input is low, those drivers are disabled, and their outputs are off and in the high-impedance state. With the proper data inputs, each pair of drivers forms a full-H (or bridge) reversible drive suitable for solenoid or motor applications.
On the L293, external high-speed output clamp diodes should be used for inductive transient suppression. On the L293D, these diodes are integrated to reduce system complexity and overall system size. A VCC1 terminal, separate from VCC2, is provided for the logic inputs to minimize device power dissipation. The L293 and L293D" - Texas Instruments
• Screw on the brackets to the front of the rover according to the picture(s) below. (Dont pay attention to the other stuff behind it, we'll get to that in a moment).
• (OPTIONAL) For the LEFT and RIGHT brackets, I like to leave off the screws that are closest to the center bracket, allowing the bracket to swivel to different angles.
• Place your Raspberry-Pi in the location according to the picture below.
• Top DC wire -> OUT4
• Bottom DC wire -> OUT3
• GPIO-14 -> EN2
• GPIO-15 -> IN4
• GPIO-18 -> IN3
• Top DC wire -> OUT1
• Bottom DC wire -> OUT2
• GPIO-23 -> EN1
• GPIO-24 -> IN1
• GPIO-25 -> IN2
• Top DC wire -> OUT1
• Bottom DC wire -> OUT2
• GPIO-08 -> EN1
• GPIO-07 -> IN1
• GPIO-25 -> IN2
• Top DC wire -> OUT4
• Bottom DC wire -> OUT3
• GPIO-16 -> EN2
• GPIO-20 -> IN4
• GPIO-21 -> IN3
• Follow the diagram to connect all ground units to GND pin on the Rasperry-Pi.
• Connect the battery clip-connector's positive and negative wires into the breadboard according to the diagram below. *DO NOT PLUG THE BATTERY INTO THE CLIP-CONNECTOR YET!
• Connect the 5v Raspberry-Pi pin to the breadboard according to the diagram below.
• Insert the HC-SR04 sensor into the bracket as seen in the picture(s) below.
• Attach the female to male jumper wires to the pins on the sensor as seen below.
• Repeat for last 2 sensors.
• Red wire - VCC
• Green wire - Trig
• Blue wire - Echo
• Black wire - GND
• Screw on the Top Metal Plate to the back of the rover so that it sits just above the Raspberry-Pi like in the picture below.
• Place the power bank under the breadboard and as shown in the picture below.
• Place the Arduino on top of the Top Metal Plate. (Picture in Step 9).
• Follow the diagram bellow to make the connections. Add another mini-breadboard in front of the breadboard sitting on top of the power-bank as shown in the picture(s) above and below to allow the sensors to receive power and communicate with the Arduino.
• The HC-SR04 sensors send out an ultrasonic pulse, then a distance is calculated based on the time the pulse's echo takes to return to the sensor. Read more about the HC-SR04 sensor here
Left Trigger Pin - 13
Left Echo Pin - 12
Middle Trigger Pin - 9
Middle Echo Pin - 11
Right Trigger Pin - 8
Right Echo Pin - 10
• SSH into your Raspberry-Pi.
• Type cd ~ and press enter.
• Type mkdir RaspberryPi/Rovers and press enter.
• Type cd RaspberryPi/Rovers and press enter.
• From your Mac or PC, create a similar directory, but add a file that directory: ~/RaspberryPi/Rovers/autonomous_rover_001.py
• Open the ~/RaspberryPi/Rovers/autonomous_rover_001.py file and copy the code below to place inside.
• Navigate to the Rovers directory in your terminal. If on Mac or Linux, type the following command to copy the autonomous_rover_001.py file into your RaspberryPi's directory: scp autonomous_rover_001.py pi@ip_address:/home/pi/Rovers
• After entering the password, you should see something like this: autonomous_rover_001.py 100% 6892 877.3KB/s 00:00
• Check your RaspberryPi's directory to make sure the file transferred (You should still be in your /Rovers directory): sudo nano autonomous_rover_001.py
• Make sure the code is there and correct, then press control + X to exit.
The code below is written using Python3. To learn more about Python3 programming, visit here
### Code to copy:
import RPi.GPIO as GPIO
import time
from time import sleep
import pygame
import serial
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
# Autonomous or Controller:
a = input("Autonomous Mode? T/F: ")
if a == "T":
AUTONOMOUS_MODE = True
else:
AUTONOMOUS_MODE = False
### MOTORS
FREQUENCY = 20
DUTY_CYCLE = 90
PWM_STOP = 0
## FRONT RIGHT
Motor_FrontR_1 = 7
Motor_FrontR_2 = 12
Motor_FrontR_Enable = 8
GPIO.setup(Motor_FrontR_1, GPIO.OUT)
GPIO.setup(Motor_FrontR_2, GPIO.OUT)
GPIO.setup(Motor_FrontR_Enable, GPIO.OUT)
## BACK RIGHT
Motor_BackR_3 = 21
Motor_BackR_4 = 20
Motor_BackR_Enable = 16
GPIO.setup(Motor_BackR_3, GPIO.OUT)
GPIO.setup(Motor_BackR_4, GPIO.OUT)
GPIO.setup(Motor_BackR_Enable, GPIO.OUT)
## FRONT LEFT
Motor_FrontR_1 = 7
Motor_FrontR_2 = 12
Motor_FrontR_Enable = 8
GPIO.setup(Motor_FrontR_1, GPIO.OUT)
GPIO.setup(Motor_FrontR_2, GPIO.OUT)
GPIO.setup(Motor_FrontR_Enable, GPIO.OUT)
## BACK RIGHT
Motor_BackR_3 = 21
Motor_BackR_4 = 20
Motor_BackR_Enable = 16
GPIO.setup(Motor_BackR_3, GPIO.OUT)
GPIO.setup(Motor_BackR_4, GPIO.OUT)
GPIO.setup(Motor_BackR_Enable, GPIO.OUT)
## FRONT LEFT
Motor_FrontL_3 = 18
Motor_FrontL_4 = 15
Motor_FrontL_Enable = 14
GPIO.setup(Motor_FrontL_3, GPIO.OUT)
GPIO.setup(Motor_FrontL_4, GPIO.OUT)
GPIO.setup(Motor_FrontL_Enable, GPIO.OUT)
## BACK LEFT
Motor_BackL_1 = 24
Motor_BackL_2 = 25
Motor_BackL_Enable = 23
GPIO.setup(Motor_BackL_1, GPIO.OUT)
GPIO.setup(Motor_BackL_2, GPIO.OUT)
GPIO.setup(Motor_BackL_Enable, GPIO.OUT)
# Set up PWM pins:
pwmMotor_FrontR_1 = GPIO.PWM(Motor_FrontR_1, FREQUENCY)
pwmMotor_FrontR_2 = GPIO.PWM(Motor_FrontR_2, FREQUENCY)
pwmMotor_BackR_3 = GPIO.PWM(Motor_BackR_3, FREQUENCY)
pwmMotor_BackR_4 = GPIO.PWM(Motor_BackR_4, FREQUENCY)
pwmMotor_FrontL_3 = GPIO.PWM(Motor_FrontL_3, FREQUENCY)
pwmMotor_FrontL_4 = GPIO.PWM(Motor_FrontL_4, FREQUENCY)
pwmMotor_BackL_1 = GPIO.PWM(Motor_BackL_1, FREQUENCY)
pwmMotor_BackL_2 = GPIO.PWM(Motor_BackL_2, FREQUENCY)
# Initial PWM Start:
pwmMotor_FrontR_1.start(PWM_STOP)
pwmMotor_FrontR_2.start(PWM_STOP)
pwmMotor_BackR_3.start(PWM_STOP)
pwmMotor_BackR_4.start(PWM_STOP)
pwmMotor_FrontL_3.start(PWM_STOP)
pwmMotor_FrontL_4.start(PWM_STOP)
pwmMotor_BackL_1.start(PWM_STOP)
pwmMotor_BackL_2.start(PWM_STOP)
# PWM Control:
def pwm_stop():
pwmMotor_FrontR_1.ChangeDutyCycle(PWM_STOP)
pwmMotor_FrontR_2.ChangeDutyCycle(PWM_STOP)
pwmMotor_BackR_3.ChangeDutyCycle(PWM_STOP)
pwmMotor_BackR_4.ChangeDutyCycle(PWM_STOP)
pwmMotor_FrontL_3.ChangeDutyCycle(PWM_STOP)
pwmMotor_FrontL_4.ChangeDutyCycle(PWM_STOP)
pwmMotor_BackL_1.ChangeDutyCycle(PWM_STOP)
pwmMotor_BackL_2.ChangeDutyCycle(PWM_STOP)
def pwm_forward():
# Front Right Motors
pwmMotor_FrontR_1.ChangeDutyCycle(PWM_STOP)
pwmMotor_FrontR_2.ChangeDutyCycle(DUTY_CYCLE)
GPIO.output(Motor_FrontR_Enable, GPIO.HIGH)
# Back Right Motors
pwmMotor_BackR_3.ChangeDutyCycle(PWM_STOP)
pwmMotor_BackR_4.ChangeDutyCycle(DUTY_CYCLE)
GPIO.output(Motor_BackR_Enable, GPIO.HIGH)
# Front Left Motors
pwmMotor_FrontL_3.ChangeDutyCycle(DUTY_CYCLE)
pwmMotor_FrontL_4.ChangeDutyCycle(PWM_STOP)
GPIO.output(Motor_FrontL_Enable, GPIO.HIGH)
# Back Left Motors
pwmMotor_BackL_1.ChangeDutyCycle(DUTY_CYCLE)
pwmMotor_BackL_2.ChangeDutyCycle(PWM_STOP)
GPIO.output(Motor_BackL_Enable, GPIO.HIGH)
def pwm_backward():
# Front Right Motors
pwmMotor_FrontR_1.ChangeDutyCycle(DUTY_CYCLE)
pwmMotor_FrontR_2.ChangeDutyCycle(PWM_STOP)
GPIO.output(Motor_FrontR_Enable, GPIO.HIGH)
# Back Right Motors
pwmMotor_BackR_3.ChangeDutyCycle(DUTY_CYCLE)
pwmMotor_BackR_4.ChangeDutyCycle(PWM_STOP)
GPIO.output(Motor_BackR_Enable, GPIO.HIGH)
# Front Left Motors
pwmMotor_FrontL_3.ChangeDutyCycle(PWM_STOP)
pwmMotor_FrontL_4.ChangeDutyCycle(DUTY_CYCLE)
GPIO.output(Motor_FrontL_Enable, GPIO.HIGH)
# Back Left Motors
pwmMotor_BackL_1.ChangeDutyCycle(PWM_STOP)
pwmMotor_BackL_2.ChangeDutyCycle(DUTY_CYCLE)
GPIO.output(Motor_BackL_Enable, GPIO.HIGH)
def pwm_right():
# Front Left Motors
pwmMotor_FrontL_3.ChangeDutyCycle(DUTY_CYCLE)
pwmMotor_FrontL_4.ChangeDutyCycle(PWM_STOP)
GPIO.output(Motor_FrontL_Enable, GPIO.HIGH)
# Back Left Motors
pwmMotor_BackL_1.ChangeDutyCycle(DUTY_CYCLE)
pwmMotor_BackL_2.ChangeDutyCycle(PWM_STOP)
GPIO.output(Motor_BackL_Enable, GPIO.HIGH)
def pwm_left():
# Front Right Motors
pwmMotor_FrontR_1.ChangeDutyCycle(PWM_STOP)
pwmMotor_FrontR_2.ChangeDutyCycle(DUTY_CYCLE)
GPIO.output(Motor_FrontR_Enable, GPIO.HIGH)
# Back Right Motors
pwmMotor_BackR_3.ChangeDutyCycle(PWM_STOP)
pwmMotor_BackR_4.ChangeDutyCycle(DUTY_CYCLE)
GPIO.output(Motor_BackR_Enable, GPIO.HIGH)
def drive_autonomously():
ser = serial.Serial('/dev/ttyACM0', 115200)
ser = ser.readline().decode("utf-8", "ignore")
for s in ser:
if '1' == s:
print("FORWARD!")
pwm_forward()
elif '2' == s:
pwm_stop()
time.sleep(2)
pwm_right()
time.sleep(1.25)
print("RIGHT!")
pwm_stop()
time.sleep(2)
elif '3' == s:
pwm_stop()
time.sleep(2)
pwm_backward()
time.sleep(1)
print("BACK!")
pwm_stop()
time.sleep(2)
elif '4' == s:
pwm_stop()
time.sleep(2)
pwm_left()
time.sleep(1.25)
print("LEFT!")
pwm_stop()
time.sleep(2)
if __name__ == '__main__':
try:
while True:
if AUTONOMOUS_MODE == True:
drive_autonomously()
else:
pygame.init()
pygame.joystick.init()
j = pygame.joystick.Joystick(0)
j.init()
#print("DRIVER_MODE")
events = pygame.event.get()
for event in events:
if event.type == pygame.JOYBUTTONDOWN:
if j.get_button(3):
print("Moving Forward")
pwm_forward()
elif j.get_button(1):
print("Moving Backward")
pwm_backward()
elif j.get_button(2):
print("Moving Right")
pwm_right()
elif j.get_button(0):
print("Moving Left")
pwm_left()
elif event.type == pygame.JOYBUTTONUP:
pwm_stop()
print("Listening...")
except KeyboardInterrupt:
print("Shutting Down and Cleaning Up")
pwm_stop()
GPIO.cleanup()
• If you haven't already, download the Arduino IDE for either Windows or Mac OS X.
• Open a new file in the IDE and copy the code below and save it as autonomous_rover_001_hcsr04.
• Use the USB A male to B male cable to connect your computer to your Arduino.
• Compile the code by clicking on the "check mark" in the top nav-bar of the Arduino IDE to verify.
• Upload the code by clicking on the "right arrow" in the top nav-bar of the Arduino IDE to upload your code to your Arduino board.
• If you want to test the sensors right now, click up top on "tools", and then click on "Serial Monitor". Move your hands around the sensors to gauge its sensitivity.
• If no errors occur, click the "arrow pointing to the right" in the top nav-bar of the Arduino IDE to upload the code to the Arduino board.
The code below is C/C++ which is used by Arduino. Read more about learning Arduino code here
(If you do not see a white-background below, please refresh your page)
const int trigPinLeft = 13;
const int echoPinLeft = 12;
const int trigPinMiddle = 9;
const int echoPinMiddle = 11;
const int trigPinRight = 8;
const int echoPinRight = 10;
long duration;
int distanceLeft;
int distanceMiddle;
int distanceRight;
void setup() {
pinMode(trigPinLeft, OUTPUT);
pinMode(echoPinLeft, INPUT);
pinMode(trigPinMiddle, OUTPUT);
pinMode(echoPinMiddle, INPUT);
pinMode(trigPinRight, OUTPUT);
pinMode(echoPinRight, INPUT);
Serial.begin(115200);
}
void loop() {
digitalWrite(trigPinLeft, LOW);
delayMicroseconds(2);
digitalWrite(trigPinLeft, HIGH);
delayMicroseconds(10);
digitalWrite(trigPinLeft, LOW);
duration = pulseIn(echoPinLeft, HIGH);
distanceLeft = duration * 0.034 / 2;
digitalWrite(trigPinMiddle, LOW);
delayMicroseconds(2);
digitalWrite(trigPinMiddle, HIGH);
delayMicroseconds(10);
digitalWrite(trigPinMiddle, LOW);
duration = pulseIn(echoPinMiddle, HIGH);
distanceMiddle = duration * 0.034 / 2;
digitalWrite(trigPinRight, LOW);
delayMicroseconds(2);
digitalWrite(trigPinRight, HIGH);
delayMicroseconds(10);
digitalWrite(trigPinRight, LOW);
duration = pulseIn(echoPinRight, HIGH);
distanceRight = duration * 0.034 / 2;
if(distanceMiddle < 100){
if(distanceRight < 30 && distanceLeft < 30){
// Move Backwards
Serial.println("3");
}else if(distanceRight > distanceLeft){
// Move Right
Serial.println("2");
}else{
// Move Left
Serial.println("4");
}
}else if(distanceRight < 30){
// Move Left
Serial.println("4");
}else if(distanceLeft < 30){
// Move Right
Serial.println("2");
}else if(distanceRight < 30 && distanceLeft < 30){
// Move Backwards
Serial.println("3");
}else{
// Move Forward
Serial.println("1");
}
}
• If you can, try to get a couple boxes together to create an enclosure to allow your vehicle to maneuver around in. Maybe even throw in some obstacles in the middle of the enclosure as well to make things more interesting.
• Plug the Arduino into the Raspberry-Pi using the USB A to B cable. The rectangular end will go into the USB port of the Rasberry-Pi, and the box/square shaped end will plug into the Arduino.
• Place your vehicle in the enclosure and from your Raspberry-Pi's /Rovers directory, type sudo python3 autonomous_rover_001.py. When the program asks if you would like to engage Autonomous-Mode, type T (make sure it's capital) and press enter.
• The Raspberry-Pi will begin taking serial data from the Arduino to make decisions on how to maneuver based on those readings.
• Feel free to tweak the distances, baud rate, etc... of the vehicle in the code to your preference.
• If your vehicle is moving too slow you can change the DUTY_CYCLE to a higher number in the Raspberry-Pi code, not exceeding 100 though.
• To stop the program, simply type control + C.
• When you're ready to turn off your Raspberry-Pi, type sudo shutdown -h now and then press enter. Wait at least 30 seconds before removing the power USB cable from the power bank.
• Have fun and enjoy your autonomous vehicle. Remember, you can always add more sensors to the sides and back of the vehicle as well as a camera!