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.
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)
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] & (0x01 << I2C_DEVICE_DGPS)) :
UTC = ((long)(BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][0]<<24)) + ((long)(BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][1]<<16)) + ((long)(BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][2]<<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] & (0x01 << I2C_DEVICE_DGPS)) :
lon = ((long)(BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][0]<<24)) + ((long)(BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][1]<<16)) + ((long)(BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][2]<<8)) + (long)(BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][3])
if BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][0]>10: #if the 0th byte >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] & (0x01 << I2C_DEVICE_DGPS)) :
lat = ((long)(BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][0]<<24)) + ((long)(BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][1]<<16)) + ((long)(BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][2]<<8)) + (long)(BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][3])
if BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][0]>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] & (0x01 << I2C_DEVICE_DGPS)) :
head = ((long)(BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][0]<<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] & (0x01 << 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] & (0x01 << I2C_DEVICE_DGPS)) :
velo = ((long)(BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][0]<<16)) + ((long)(BrickPi.SensorI2CIn[I2C_PORT][I2C_DEVICE_DGPS][1]<<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
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?