The Auto_Tank


#1

I just wanted to share a project I have been working on since I received my BrickPi.

I call it the Auto_Tank (picture and code attached).

Basically it is just the Lego build from the Rigraptor Tank (http://www.dexterindustries.com/BrickPi/projects/tank/) with the following mods:

Added an NXT Ultrasonic Sensor
Added a DI-dGPS
Added a Pi Camera

The code allows the tank to autonomously travel around a room and detect obstacles with the US sensor. When an object is detected, the tank backs up and turns and then proceeds forward again. Every 60 seconds, the Tank tweets its current GPS coordinates. The Pi camera streams live video (great tutorial here: http://blog.miguelgrinberg.com/post/stream-video-from-the-raspberry-pi-camera-to-web-browsers-even-on-ios-and-android) which can be viewed via the web.

Follow the tutorial for the Twitter Weather Station if you have trouble understanding my notes in the TweetTank module. Make sure to fill in your own Twitter credentials in the code where instructed.

The project was fun to do with my 11 year old son, although he was more interested in building the Tank than coding!

I borrowed heavily from existing programs (giving credit of course) but in the process learned how to set up internal threading and calling and running modules.

The Pi camera is launched separate from the attached code following Miguel Grinberg’s great instructions as listed above. Props to Miguel as this is the best implementation of streaming from the Pi Camera I have found. I made his instructions into an executable file that I launch from the Pi GUI. The rest of the tank actions can be launched just by running Auto_Tank.py. Make sure Auto_Tank.py and DI_dGPS_TweetTank2.py are in the same directory.

Hope folks find this fun and useful. Obviously feel free to modify and then share any mods back.

Steve


#2

Apologies, the code files would not load. Here is the code for Auto_Tank:

`# Adapted from Jaikrishna Robot Arm

StevenL89 11-09-13

Auto Tank

from BrickPi import * # Import BrickPi.py file to use BrickPi operations
import time # Time for sleep function
import threading # To control background tasks
import DI_dGPS_TweetTank2 # GPS coordinates are tweeted every 60 secs

BrickPiSetup() # Setup the serial port for communication

BrickPi.MotorEnable[PORT_A] = 1 # Enable the Motor A
BrickPi.MotorEnable[PORT_D] = 1 # Enable the Motor D

BrickPi.SensorType[PORT_4] = TYPE_SENSOR_ULTRASONIC_CONT # Set the type of sensor at PORT_4

BrickPiSetupSensors() # Send the properties of sensors to BrickPi

BrickPiUpdateValues() # Update values

running = True

class myThread (threading.Thread): # This thread is used for keeping the GPS running while the main thread waits for input from the ultrasonic sensor and controls motors
def init(self, threadID, name, counter):
threading.Thread.init(self)
self.threadID = threadID
self.name = name
self.counter = counter
def run(self):
while running:
if BrickPi.Sensor[PORT_4] < 35:
BrickPi.MotorSpeed[PORT_A] = -200
BrickPi.MotorSpeed[PORT_D] = 200
else:
BrickPi.MotorSpeed[PORT_A] = 200
BrickPi.MotorSpeed[PORT_D] = 200

        BrickPiUpdateValues()       # Ask BrickPi to update values for se
        time.sleep(.2)              # Sleep for 200 ms

thread1 = myThread(1, “Thread-1”, 1) # Setup and start the thread
thread1.setDaemon(True)
thread1.start()

while True:
try:
DI_dGPS_TweetTank2.runModule() # Load and run GPS Tweeting function
time.sleep(60)

except KeyboardInterrupt:
    running = False
    print 'Done'
    break

#3

Here is the code for DI_dGPS_TweetTank2.py:

`

Modified from DI-dGPS_test.py

This code is for testing the BrickPi with a GPS sensor from Dexter Industries

Product webpage: http://www.dexterindustries.com/dGPS.html

History

------------------------------------------------

Author Date Comments

Jaikrishna June 24, 2013 Initial Authoring

Karan Nov 7, 2013 Change to the longitude and latitude code

StevenL89 Nov 9, 2013 Add Twitter function and modify as a module for Auto_Tank

Coding for Twitter access adapted from Twitter Weather Station http://www.dexterindustries.com/BrickPi/projects/twitter-tweeter/

You will need to install Twython

http://www.dexterindustries.com/

from BrickPi import * # Import BrickPi.py file to use BrickPi operations
import time # Imports time
from twython import Twython, TwythonError # Sets up for Twitter access

def runModule(): # Defines this program as a module to be accesses by Auto_Tank

I2C_PORT  = PORT_3                            # I2C port for the dGPS
I2C_SPEED = 0                                 # delay for as little time as possible. Usually about 100k baud
I2C_DEVICE_DGPS = 0                        	# dGPS is device 0 on this I2C bus

DGPS_I2C_ADDR   = 0x06      # Barometric sensor device address 
DGPS_CMD_UTC    = 0x00      # Fetch UTC 
DGPS_CMD_STATUS = 0x01      # Status of satellite link: 0 no link, 1 link 
DGPS_CMD_LAT    = 0x02      # Fetch Latitude 
DGPS_CMD_LONG   = 0x04      # Fetch Longitude 
DGPS_CMD_VELO   = 0x06      # Fetch velocity in cm/s 
DGPS_CMD_HEAD   = 0x07      # Fetch heading in degrees 



BrickPiSetup()  # setup the serial port for communication

# Setup keys for Twitter
APP_KEY = "ADD YOUR APP_KEY"
APP_SECRET = "ADD YOUR APP_SECRET"
OAUTH_TOKEN = "ADD YOUR TOKEN" #
OAUTH_TOKEN_SECRET = "ADD YOUR TOKEN SECRET" #

twitter = Twython(APP_KEY, APP_SECRET, OAUTH_TOKEN, OAUTH_TOKEN_SECRET) # Setup a Twython object


BrickPi.SensorType[I2C_PORT] = TYPE_SENSOR_I2C 	# Set the type of sensor at PORT_3
BrickPi.SensorI2CSpeed[I2C_PORT] = I2C_SPEED   # Set the speed of communication
BrickPi.SensorI2CDevices [I2C_PORT] = 1        # Number of devices in the I2C bus
BrickPi.SensorI2CAddr  [I2C_PORT][I2C_DEVICE_DGPS]    = DGPS_I2C_ADDR	#address for writing
BrickPi.SensorSettings [I2C_PORT][I2C_DEVICE_DGPS]    = BIT_I2C_MID	# the dGPS device requires a clock change between reading and writing
BrickPi.SensorI2CWrite [I2C_PORT][I2C_DEVICE_DGPS]    = 1				#number of bytes to write

#UTC
BrickPi.SensorI2CRead  [I2C_PORT][I2C_DEVICE_DGPS]    = 4
BrickPi.SensorI2COut   [I2C_PORT][I2C_DEVICE_DGPS][0] = DGPS_CMD_UTC	#byte to write
BrickPiSetupSensors()
result = BrickPiUpdateValues() # Write and read
if not result :
	if (BrickPi.Sensor[I2C_PORT] &amp; (0x01 &lt;&lt; I2C_DEVICE_DGPS)) :
		UTC = ((long)(BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][0]&lt;&lt;24)) + ((long)(BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][1]&lt;&lt;16)) + ((long)(BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][2]&lt;&lt;8)) + (long)(BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][3])

	#Longitude
BrickPi.SensorI2COut   [I2C_PORT][I2C_DEVICE_DGPS][0] = DGPS_CMD_LONG	#byte to write
BrickPiSetupSensors()
result = BrickPiUpdateValues() # Write and read
if not result :
	if (BrickPi.Sensor[I2C_PORT] &amp; (0x01 &lt;&lt; I2C_DEVICE_DGPS)) :
		lon = ((long)(BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][0]&lt;&lt;24)) + ((long)(BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][1]&lt;&lt;16)) + ((long)(BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][2]&lt;&lt;8)) + (long)(BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][3])
		if BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][0]&gt;10:	#if the 0th byte &gt;10, then the longitude was negative and use the 2's compliment of the longitude
			lon=(4294967295L^lon)+1
			lon=(-float(lon)/1000000)
		else:
			lon=(float(lon)/1000000)
				
	#Latitude
BrickPi.SensorI2COut   [I2C_PORT][I2C_DEVICE_DGPS][0] = DGPS_CMD_LAT	#byte to write
BrickPiSetupSensors()
result = BrickPiUpdateValues() # Write and read
if not result :
	if (BrickPi.Sensor[I2C_PORT] &amp; (0x01 &lt;&lt; I2C_DEVICE_DGPS)) :
		lat = ((long)(BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][0]&lt;&lt;24)) + ((long)(BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][1]&lt;&lt;16)) + ((long)(BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][2]&lt;&lt;8)) + (long)(BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][3])
		if BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][0]&gt;10:
			lat=(4294967295L^lat)+1
			lat=(-float(lat)/1000000)
		else:
			lat=(float(lat)/1000000)

	#Heading
BrickPi.SensorI2CRead  [I2C_PORT][I2C_DEVICE_DGPS]    = 2
BrickPi.SensorI2COut   [I2C_PORT][I2C_DEVICE_DGPS][0] = DGPS_CMD_HEAD	#byte to write
BrickPiSetupSensors()
result = BrickPiUpdateValues() # Write and read
if not result :
	if (BrickPi.Sensor[I2C_PORT] &amp; (0x01 &lt;&lt; I2C_DEVICE_DGPS)) :
		head = ((long)(BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][0]&lt;&lt;8)) + ((long)(BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][1]))
	
	#Status
BrickPi.SensorI2CRead  [I2C_PORT][I2C_DEVICE_DGPS]    = 1
BrickPi.SensorI2COut   [I2C_PORT][I2C_DEVICE_DGPS][0] = DGPS_CMD_STATUS	#byte to write
BrickPiSetupSensors()
result = BrickPiUpdateValues() # Write and read
if not result :
	if (BrickPi.Sensor[I2C_PORT] &amp; (0x01 &lt;&lt; I2C_DEVICE_DGPS)) :
		status = ((long)(BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][0]))

	#Velocity
BrickPi.SensorI2CRead  [I2C_PORT][I2C_DEVICE_DGPS]    = 3
BrickPi.SensorI2COut   [I2C_PORT][I2C_DEVICE_DGPS][0] = DGPS_CMD_VELO	#byte to write
BrickPiSetupSensors()
result = BrickPiUpdateValues() #write and read
if not result :
	if (BrickPi.Sensor[I2C_PORT] &amp; (0x01 &lt;&lt; I2C_DEVICE_DGPS)) :
		velo = ((long)(BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][0]&lt;&lt;16)) + ((long)(BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][1]&lt;&lt;8)) + ((long)(BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][2]))
	
	
	
s = 'Time: ' + time.strftime('%X') + ' Heading: ' + str(head) + ' Longitude: ' +str(lon) + ' Latitude: ' + str(lat) + ' Velocity: ' + str(velo)
try:
	twitter.update_status(status=s)
	print "Tweeted:",s
except TwythonError as e:
	print "Error occured:", e.message

#4

That is really cool, thank you for sharing! We would love to reference this in an upcoming blog on some of the projects people are doing with the BrickPi. Do you mind if we share it? If you don’t, do you mind putting another picture of two up that we can share?


#5

Sure no problem. Feel free to share. Here are some additional pics attached.


#6

One more with an overhead view.