How to Assemble a Raspberry Pi Robot Tank Step by Step

How to Assemble a Raspberry Pi Robot Tank Step by Step

Hello and welcome back, In this project, we are going to assemble a Raspberry PI robot tank provided by Adeept. This tank is designed to work with Raspberry Pi models such as 4, 3B, 3B+, 2B, and 2B+. For this project, I used the Raspberry Pi 2 model B board. But I recommend using Raspberry Pi 3 or newer boards because they come with built-in WIFI. This allows us to explore the capabilities of this robot tank more deeply.

I think it’s most important for beginners and professionals to learn AI, robotics, programming, and electronics. In this project, I will share my experience with you. You can explore this project and build your own robot.

Features of this robot tank kit

  • Line tracking.
  • Obstacle avoidance.
  • Motion tracking.
  • WIFI control (WIFI Raspberry Pi boards only).
  • Real-time video transmission.
  • 4-DOF robotic arm.
  • RGB light system.

You can buy this robot tank kit using the links below.

OK, let’s do this project step by step. For that, follow the steps below.

Step 1

Firstly, let’s identify the components included in the package.

Step 2

Secondly, get the acrylic sheets and remove all the protective stickers.

Step 3

Thirdly, assemble this robot arm step by step. For that, use the PDF below.

Step 4

Next, insert the micro SD card (OS is installed) into the Raspberry Pi board. And then, connect the mouse, keyboard, network, and monitor to the Raspberry Pi board. After, connect the 5v power supply to the board.

Step 5

Now, install the required library files. For that, copy and paste the following script on the Thonny IDE. And then, click the run button.

import os
import time

curpath = os.path.realpath(__file__)
thisPath = "/" + os.path.dirname(curpath)

def replace_num(file,initial,new_num):
    newline=""
    str_num=str(new_num)
    with open(file,"r") as f:
        for line in f.readlines():
            if(line.find(initial) == 0):
                line = (str_num+'\n')
            newline += line
    with open(file,"w") as f:
        f.writelines(newline)

commands_1 = [
    "sudo apt-get update",
    "sudo apt-get purge -y wolfram-engine",
    "sudo apt-get purge -y libreoffice*",
    "sudo apt-get -y clean",
    "sudo apt-get -y autoremove",
    "sudo pip3 install -U pip",
    "sudo apt-get install -y python-dev python-pip libfreetype6-dev libjpeg-dev build-essential",
    "sudo apt-get install -y i2c-tools",
    "sudo -H pip3 install --upgrade luma.oled",
    "sudo pip3 install adafruit-pca9685",
    "sudo pip3 install rpi_ws281x",
    "sudo apt-get install -y python3-smbus",
    "sudo pip3 install mpu6050-raspberrypi",
    "sudo pip3 install flask",
    "sudo pip3 install flask_cors",
    "sudo pip3 install websockets",
    "sudo apt-get install -y libjasper-dev",
    "sudo apt-get install -y libatlas-base-dev",
    "sudo apt-get install -y libgstreamer1.0-0"
]

mark_1 = 0
for x in range(3):
    for command in commands_1:
        if os.system(command) != 0:
            print("Error running installation step 1")
            mark_1 = 1
    if mark_1 == 0:
        break


commands_2 = [
    "sudo pip3 install RPi.GPIO",
    "sudo apt-get -y install libqtgui4 libhdf5-dev libhdf5-serial-dev libatlas-base-dev libjasper-dev libqt4-test",
    "sudo pip3 install -r //home/pi/adeept_rasptank/server/requirements.txt",
    "sudo git clone https://github.com/oblique/create_ap",
    "cd " + thisPath + "/create_ap && sudo make install",
    "cd //home/pi/create_ap && sudo make install",
    "sudo apt-get install -y util-linux procps hostapd iproute2 iw haveged dnsmasq"
]

mark_2 = 0
for x in range(3):
    for command in commands_2:
        if os.system(command) != 0:
            print("Error running installation step 2")
            mark_2 = 1
    if mark_2 == 0:
        break

commands_3 = [
    "sudo pip3 install numpy",
    "sudo pip3 install opencv-contrib-python==3.4.3.18",
    # "sudo pip3 install opencv-contrib-python==3.4.17.61",
    "sudo pip3 install imutils zmq pybase64 psutil"
]

mark_3 = 0
for x in range(3):
    for command in commands_3:
        if os.system(command) != 0:
            print("Error running installation step 3")
            mark_3 = 1
    if mark_3 == 0:
        break


try:
    replace_num("/boot/config.txt", '#dtparam=i2c_arm=on','dtparam=i2c_arm=on\nstart_x=1\n')
except:
    print('Error updating boot config to enable i2c. Please try again.')



try:
    os.system('sudo touch //home/pi/startup.sh')
    with open("//home/pi/startup.sh",'w') as file_to_write:
        #you can choose how to control the robot
        file_to_write.write("#!/bin/sh\nsudo python3 " + thisPath + "/server/webServer.py")
#       file_to_write.write("#!/bin/sh\nsudo python3 " + thisPath + "/server/server.py")
except:
    pass


os.system('sudo chmod 777 //home/pi/startup.sh')

replace_num('/etc/rc.local','fi','fi\n//home/pi/startup.sh start')

try: #fix conflict with onboard Raspberry Pi audio
    os.system('sudo touch /etc/modprobe.d/snd-blacklist.conf')
    with open("/etc/modprobe.d/snd-blacklist.conf",'w') as file_to_write:
        file_to_write.write("blacklist snd_bcm2835")
except:
    pass
try:
    os.system("sudo cp -f //home/pi/adeept_rasptank/server/config.txt //etc/config.txt")
except:
    os.system("sudo cp -f "+ thisPath  +"/adeept_rasptank/server/config.txt //etc/config.txt")
print('The program in Raspberry Pi has been installed, disconnected and restarted. \nYou can now power off the Raspberry Pi to install the camera and driver board (Robot HAT). \nAfter turning on again, the Raspberry Pi will automatically run the program to set the servos port signal to turn the servos to the middle position, which is convenient for mechanical assembly.')
print('restarting...')
os.system("sudo reboot")

Step 6

Now, copy and paste the main script on the thorny IDE. It’s as follows.

  • Main script and library script — Download
from __future__ import division
import time
import RPi.GPIO as GPIO
import sys
import Adafruit_PCA9685

#Ultrasonic pins
Tr = 11
Ec = 8

pwm = Adafruit_PCA9685.PCA9685()
pwm.set_pwm_freq(50)

# motor_EN_A: Pin7  |  motor_EN_B: Pin11
# motor_A:  Pin8,Pin10    |  motor_B: Pin13,Pin12

Motor_A_EN    = 4
Motor_B_EN    = 17

Motor_A_Pin1  = 14
Motor_A_Pin2  = 15
Motor_B_Pin1  = 27
Motor_B_Pin2  = 18

Dir_forward   = 0
Dir_backward  = 1

left_forward  = 0
left_backward = 1

right_forward = 0
right_backward= 1

pwn_A = 0
pwm_B = 0

speed_set = 70

line_pin_right = 19
line_pin_middle = 16
line_pin_left = 20

def setup():
    GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BCM)
    #Line tracking sensor pins
    GPIO.setup(line_pin_right,GPIO.IN)
    GPIO.setup(line_pin_middle,GPIO.IN)
    GPIO.setup(line_pin_left,GPIO.IN)
    #Ultrasonic sensor
    GPIO.setup(Tr, GPIO.OUT,initial=GPIO.LOW)
    GPIO.setup(Ec, GPIO.IN)
    #motor.setup()
    global pwm_A, pwm_B
    GPIO.setup(Motor_A_EN, GPIO.OUT)
    GPIO.setup(Motor_B_EN, GPIO.OUT)
    GPIO.setup(Motor_A_Pin1, GPIO.OUT)
    GPIO.setup(Motor_A_Pin2, GPIO.OUT)
    GPIO.setup(Motor_B_Pin1, GPIO.OUT)
    GPIO.setup(Motor_B_Pin2, GPIO.OUT)

    motorStop()
    try:
        pwm_A = GPIO.PWM(Motor_A_EN, 1000)
        pwm_B = GPIO.PWM(Motor_B_EN, 1000)
    except:
        pass
    


def motorStop():#Motor stops
    GPIO.output(Motor_A_Pin1, GPIO.LOW)
    GPIO.output(Motor_A_Pin2, GPIO.LOW)
    GPIO.output(Motor_B_Pin1, GPIO.LOW)
    GPIO.output(Motor_B_Pin2, GPIO.LOW)
    GPIO.output(Motor_A_EN, GPIO.LOW)
    GPIO.output(Motor_B_EN, GPIO.LOW)



def motor_left(status, direction, speed):#Motor 2 positive and negative rotation
    if status == 0: # stop
        GPIO.output(Motor_B_Pin1, GPIO.LOW)
        GPIO.output(Motor_B_Pin2, GPIO.LOW)
        GPIO.output(Motor_B_EN, GPIO.LOW)
    else:
        if direction == Dir_backward:
            GPIO.output(Motor_B_Pin1, GPIO.HIGH)
            GPIO.output(Motor_B_Pin2, GPIO.LOW)
            pwm_B.start(100)
            pwm_B.ChangeDutyCycle(speed)
        elif direction == Dir_forward:
            GPIO.output(Motor_B_Pin1, GPIO.LOW)
            GPIO.output(Motor_B_Pin2, GPIO.HIGH)
            pwm_B.start(0)
            pwm_B.ChangeDutyCycle(speed)


def motor_right(status, direction, speed):#Motor 1 positive and negative rotation
    if status == 0: # stop
        GPIO.output(Motor_A_Pin1, GPIO.LOW)
        GPIO.output(Motor_A_Pin2, GPIO.LOW)
        GPIO.output(Motor_A_EN, GPIO.LOW)
    else:
        if direction == Dir_forward:#
            GPIO.output(Motor_A_Pin1, GPIO.HIGH)
            GPIO.output(Motor_A_Pin2, GPIO.LOW)
            pwm_A.start(100)
            pwm_A.ChangeDutyCycle(speed)
        elif direction == Dir_backward:
            GPIO.output(Motor_A_Pin1, GPIO.LOW)
            GPIO.output(Motor_A_Pin2, GPIO.HIGH)
            pwm_A.start(0)
            pwm_A.ChangeDutyCycle(speed)
    return direction


def move(speed, direction, turn, radius=0.6):   # 0 < radius <= 1  
    #speed = 100
    if direction == 'forward':
        if turn == 'right':
            motor_left(0, left_backward, int(speed*radius))
            motor_right(1, right_forward, speed)
        elif turn == 'left':
            motor_left(1, left_forward, speed)
            motor_right(0, right_backward, int(speed*radius))
        else:
            motor_left(1, left_forward, speed)
            motor_right(1, right_forward, speed)
    elif direction == 'backward':
        if turn == 'right':
            motor_left(0, left_forward, int(speed*radius))
            motor_right(1, right_backward, speed)
        elif turn == 'left':
            motor_left(1, left_backward, speed)
            motor_right(0, right_forward, int(speed*radius))
        else:
            motor_left(1, left_backward, speed)
            motor_right(1, right_backward, speed)
    elif direction == 'no':
        if turn == 'right':
            motor_left(1, left_backward, speed)
            motor_right(1, right_forward, speed)
        elif turn == 'left':
            motor_left(1, left_forward, speed)
            motor_right(1, right_backward, speed)
        else:
            motorStop()
    else:
        pass

def startServo():
    pwm.set_pwm(11, 0, 240) #160 - 250 
    pwm.set_pwm(12, 0, 400) # 400 - 200 
    pwm.set_pwm(13, 0, 280) # 70 - 300 
    pwm.set_pwm(14, 0, 300) # 100 - 500
    pwm.set_pwm(15, 0, 285) # 100 - 285


def destroy():
    motorStop()
    GPIO.cleanup()             # Release resource

def lineTracking():
    pwm.set_pwm(11, 0, 240)
    right = GPIO.input(line_pin_right)
    middle = GPIO.input(line_pin_middle)
    left = GPIO.input(line_pin_left)
    
    if middle == 1 and right == 0 and left == 0:
        move(speed_set, 'forward', 'no', 0.8)
    elif middle == 0 and right == 0 and left == 0:
        motorStop()
    elif middle == 1 and right == 1 and left == 1:
        motorStop()
    elif middle == 0 and right == 0 and left == 1:
        motor_left(1,Dir_backward,speed_set)
        motor_right(1,Dir_forward,speed_set)
    elif middle == 0 and right == 1 and left == 0:
        motor_left(1,Dir_forward,speed_set)
        motor_right(1,Dir_backward,speed_set)    
    elif middle == 1 and right == 0 and left == 1:
        motor_left(1,Dir_backward,speed_set)
        motor_right(1,Dir_forward,speed_set)
    elif middle == 1 and right == 1 and left == 0:
        motor_left(1,Dir_forward,speed_set)
        motor_right(1,Dir_backward,speed_set)

def lineObstacle():
    pwm.set_pwm(11, 0, 240)
    right = GPIO.input(line_pin_right)
    middle = GPIO.input(line_pin_middle)
    left = GPIO.input(line_pin_left)
    
    distance = checkdist()
    
    if distance < 10 :
        motorStop()
        move(speed_set, 'backward', 'no', 0.8)
        time.sleep(0.1)
        motorStop()
        robotArm()
        time.sleep(0.1)
    else:
        lineTracking()
            
    
def robotArm():
    for a in range(280,80,-1):
        pwm.set_pwm(13, 0, a)
        time.sleep(0.01)
        
    for a in range(285,150,-1):
        pwm.set_pwm(15, 0, a)
        time.sleep(0.01)
    
    for a in range(400,120,-1):
        pwm.set_pwm(12, 0, a)
        time.sleep(0.01)
            
    for a in range(150,270):
        pwm.set_pwm(15, 0, a)
        time.sleep(0.01)
    
    for a in range(120,400):
        pwm.set_pwm(12, 0, a)
        time.sleep(0.008)
        
    for a in range(80,250):
        pwm.set_pwm(13, 0, a)
        time.sleep(0.01)
    
    for a in range(300,500):
        pwm.set_pwm(14, 0, a)
        time.sleep(0.003)
        
    for a in range(500,100,-1):
        pwm.set_pwm(14, 0, a)
        time.sleep(0.003)
    
    for a in range(100,300):
        pwm.set_pwm(14, 0, a)
        time.sleep(0.003)
    
    time.sleep(0.5)
    motor_left(1,Dir_forward,speed_set)
    motor_right(1,Dir_backward,speed_set)
    time.sleep(0.6)
    motorStop()
    time.sleep(0.5)
    
    
    for a in range(250,80,-1):
        pwm.set_pwm(13, 0, a)
        time.sleep(0.01)
        
    for a in range(400,200,-1):
        pwm.set_pwm(12, 0, a)
        time.sleep(0.01)
        
    for a in range(270,150,-1):
        pwm.set_pwm(15, 0, a)
        time.sleep(0.01)
    
    for a in range(150,285):
        pwm.set_pwm(15, 0, a)
        time.sleep(0.01)
    
    for a in range(200,400):
        pwm.set_pwm(12, 0, a)
        time.sleep(0.01)
    
    for a in range(80,280):
        pwm.set_pwm(13, 0, a)
        time.sleep(0.01)
    
    time.sleep(0.5)
    motor_left(1,Dir_backward,speed_set)
    motor_right(1,Dir_forward,speed_set)
    time.sleep(0.6)
    motorStop()
    time.sleep(0.5)
    

def checkdist():       #Reading distance
    for i in range(5):  # Remove invalid test results.
        GPIO.setwarnings(False)
        GPIO.setmode(GPIO.BCM)
        GPIO.setup(Tr, GPIO.OUT,initial=GPIO.LOW)
        GPIO.setup(Ec, GPIO.IN)
        GPIO.output(Tr, GPIO.LOW)
        time.sleep(0.000002)
        GPIO.output(Tr, GPIO.HIGH)
        time.sleep(0.000015)
        GPIO.output(Tr, GPIO.LOW)
        while not GPIO.input(Ec):
            pass
        t1 = time.time()
        while GPIO.input(Ec):
            pass
        t2 = time.time()
        dist = (t2-t1)*340/2
        if dist > 9 and i < 4:  # 5 consecutive times are invalid data, return the last test data
            continue
        else:
            return dist*100
        
def cuteRobot():
    distance = checkdist()
    pwm.set_pwm(12, 0, 400) 
    pwm.set_pwm(13, 0, 280) 
    pwm.set_pwm(14, 0, 300) 
    pwm.set_pwm(15, 0, 285) 
    
    if distance < 9:
        move(speed_set, 'backward', 'no', 0.8)
        for i in range(190,210):
            pwm.set_pwm(11, 0, i)
            time.sleep(0.01)
        for i in range(210,190,-1):
            pwm.set_pwm(11, 0, i)
            time.sleep(0.01)
    else:
        move(speed_set, 'forward', 'no', 0.8)
        print("forward")

     
def servoS():
    pwm.set_pwm(12, 0, 400)
    pwm.set_pwm(13, 0, 280)
    pwm.set_pwm(14, 0, 300)
    pwm.set_pwm(15, 0, 285)
    
    

if __name__ == '__main__': 
    try:     
        setup()
        servoS()
        while True:           
#            lineObstacle()
#            cuteRobot()
#            startServo()
#            lineTracking()
    except KeyboardInterrupt:
        destroy()
  • I have created three methods. That is line tracking, line tracking with obstacle avoidance, and cute robot.
  • Now save this script to your desired location.

Step 7

Next, open the terminal and follow the instructions below.

  • sudo crontab -e
  • Now, you can see the nano editor. And then, enter your main script location. For that, use the code below.
  • @reboot python /enter your location
  • Ex:- @reboot python /home/srituhobby/Desktop/RaspTankNew.py
  • Next, press the ctrl+x and press y.
  • Finally, press the enter button.

Step 8

Now, uncomment the cute robot methode(Remove the # tag) and click the run button.

Step 9

Next, shutdown your raspberry pi computer and remove the all cables. And then, put the 18650 batteries into the robot tank. Finally, power on this robot.

Now, you can test this robot tank. Also, try the other two methods.

Ok, enjoy this project. The full video guide is below. We hope to see you in the next project or tutorial.

How to Assemble a Raspberry Pi Robot Tank Step by Step

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *