Last active
December 21, 2015 16:29
-
-
Save ibanezmatt13/6333763 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
import os | |
import serial | |
import crcmod | |
import time | |
import time as time_ | |
gps_set_success = False # boolean for the status of flightmode | |
time_set = False # boolean for status of the OS time being set | |
trigger = False | |
# byte array for a UBX command to set flight mode | |
setNav = bytearray.fromhex("B5 62 06 24 24 00 FF FF 06 03 00 00 00 00 10 27 00 00 05 00 FA 00 FA 00 64 00 2C 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 16 DC") | |
# byte array for UBX command to disable automatic NMEA response from GPS | |
setNMEA_off = bytearray.fromhex("B5 62 06 00 14 00 01 00 00 00 D0 08 00 00 80 25 00 00 07 00 01 00 00 00 00 00 A0 A9") | |
# function to disable all NMEA sentences | |
def disable_sentences(): | |
GPS = serial.Serial('/dev/ttyAMA0', 9600, timeout=1) # open serial to write to GPS | |
# Disabling all NMEA sentences | |
GPS.write("$PUBX,40,GLL,0,0,0,0*5C\r\n") | |
GPS.write("$PUBX,40,GSA,0,0,0,0*4E\r\n") | |
GPS.write("$PUBX,40,RMC,0,0,0,0*47\r\n") | |
GPS.write("$PUBX,40,GSV,0,0,0,0*59\r\n") | |
GPS.write("$PUBX,40,VTG,0,0,0,0*5E\r\n") | |
GPS.close() # close serial | |
#create function equivalent to arduino millis(); | |
def millis(): | |
return int(round(time_.time() * 1000)) | |
#calcuate expected UBX ACK packet and parse UBX response from GPS | |
def getUBX_ACK(MSG): | |
b = 0 | |
ackByteID = 0 | |
ackPacket = [0 for x in range(10)] | |
startTime = millis() | |
print "Reading ACK response: " | |
#construct the expected ACK packet | |
ackPacket[0] = int('0xB5', 16) #header | |
ackPacket[1] = int('0x62', 16) #header | |
ackPacket[2] = int('0x05', 16) #class | |
ackPacket[3] = int('0x01', 16) #id | |
ackPacket[4] = int('0x02', 16) #length | |
ackPacket[5] = int('0x00', 16) | |
ackPacket[6] = MSG[2] #ACK class | |
ackPacket[7] = MSG[3] #ACK id | |
ackPacket[8] = 0 #CK_A | |
ackPacket[9] = 0 #CK_B | |
#calculate the checksums | |
for i in range(2,8): | |
ackPacket[8] = ackPacket[8] + ackPacket[i] | |
ackPacket[9] = ackPacket[9] + ackPacket[8] | |
#print expected packet | |
print "Expected ACK Response: " | |
for byt in ackPacket: | |
print byt | |
print "Waiting for UBX ACK reply:" | |
while 1: | |
#test for success | |
if ackByteID > 9 : | |
#all packets are in order | |
print "ACK has been acknowledged successfully!" | |
return True | |
#timeout if no valid response in 3 secs | |
if millis() - startTime > 3000: | |
print "The ACK has completely failed" | |
return False | |
#make sure data is availible to read | |
if GPS.inWaiting() > 0: | |
print "serial buffer contains data" | |
b = GPS.read(1) | |
print "following byte has been read from buffer:", ord(b) | |
#check that bytes arrive in the sequence as per expected ACK packet | |
if ord(b) == ackPacket[ackByteID]: | |
print "this particular byte matches our expected response" | |
ackByteID += 1 | |
#print ord(b) | |
else: | |
ackByteID = 0 #reset and look again, invalid order | |
print "the byte doesn't match what was expected. Back to the start" | |
print "current ackByteID:", ackByteID | |
# fucntion to send commands to the GPS | |
def sendUBX(MSG, length): | |
print "Sending UBX Command: " | |
ubxcmds = "" | |
for i in range(0, length): | |
GPS.write(chr(MSG[i])) #write each byte of ubx cmd to serial port | |
ubxcmds = ubxcmds + str(MSG[i]) + " " # build up sent message debug output string | |
GPS.write("\r\n") #send newline to ublox | |
print ubxcmds #print debug message | |
print "UBX Command Sent..." | |
crc16f = crcmod.predefined.mkCrcFun('crc-ccitt-false') # function for CRC-CCITT checksum | |
disable_sentences() | |
counter = 0 # this counter will increment as our sentence_id | |
error = 0 | |
# function to send both telemetry and packets | |
def send(data): | |
NTX2 = serial.Serial('/dev/ttyAMA0', 300, serial.EIGHTBITS, serial.PARITY_NONE, serial.STOPBITS_TWO) # opening serial at 300 baud for radio transmission with 8 character bits, no parity and two stop bits | |
NTX2.write(data) # write final datastring to the serial port | |
print data | |
NTX2.close() | |
# function to read the gps and process the data it returns for transmission | |
def read_gps(flightmode_status): | |
global counter | |
GPS = serial.Serial('/dev/ttyAMA0', 9600, timeout=1) | |
start_time = millis() | |
while True: | |
NMEA_sentence = GPS.readline() | |
if "GPGGA" in NMEA_sentence: | |
error = 0 | |
GPS.close() | |
continue | |
if millis() - start_time <= 3000: | |
GPS.close() | |
error = 1 | |
string = str(callsign + ',' + time + ',' + str(counter) + ',' + str(latitude) + ',' + str(longitude) + ',' + str(flightmode_status) + ',' + str(trigger) + ',' + error + ',' + satellites + ',' + str(altitude)) # the data string | |
csum = str(hex(crc16f(string))).upper()[2:] # running the CRC-CCITT checksum | |
csum = csum.zfill(4) # creating the checksum data | |
datastring = str("$$" + string + "*" + csum + "\n") # appending the datastring as per the UKHAS communication protocol | |
counter += 1 # increment the sentence ID for next transmission | |
print "now sending the following:", datastring | |
send(datastring) # send the datastring to the send function to send to the NTX2 | |
print NMEA_sentence | |
data = NMEA_sentence.split(",") # split sentence into individual fields | |
if data[18] == "0": # if it does start with a valid sentence but with no fix | |
print "No Lock" | |
pass | |
else: # if it does start with a valid sentence and has a fix | |
# parsing required telemetry fields | |
satellites = data[18] | |
lats = data[3] | |
northsouth = data[4] | |
lngs = data[5] | |
westeast = data[6] | |
altitude = int(float(data[7])) | |
callsign = "NORB_Test" | |
time = data[2] | |
time = float(time) # ensuring that python knows time is a float | |
string = "%06i" % time # creating a string out of time (this format ensures 0 is included at start if any) | |
hours = string[0:2] | |
minutes = string[2:4] | |
seconds = string[4:6] | |
time = str(str(hours) + ':' + str(minutes) + ':' + str(seconds)) # the final time string in form 'hh:mm:ss' | |
latitude = convert(lats, northsouth) | |
longitude = convert(lngs, westeast) | |
if altitude >= 142: | |
trigger = True | |
string = str(callsign + ',' + time + ',' + str(counter) + ',' + str(latitude) + ',' + str(longitude) + ',' + str(flightmode_status) + ',' + str(trigger) + ',' + satellites + ',' + str(altitude)) # the data string | |
csum = str(hex(crc16f(string))).upper()[2:] # running the CRC-CCITT checksum | |
csum = csum.zfill(4) # creating the checksum data | |
datastring = str("$$" + string + "*" + csum + "\n") # appending the datastring as per the UKHAS communication protocol | |
counter += 1 # increment the sentence ID for next transmission | |
print "now sending the following:", datastring | |
send(datastring) # send the datastring to the send function to send to the NTX2 | |
# function to convert latitude and longitude into a different format | |
def convert(position_data, orientation): | |
decs = "" | |
decs2 = "" | |
for i in range(0, position_data.index('.') - 2): | |
decs = decs + position_data[i] | |
for i in range(position_data.index('.') - 2, len(position_data) - 1): | |
decs2 = decs2 + position_data[i] | |
position = float(decs) + float(str((float(decs2)/60))[:8]) | |
if orientation == ("S") or orientation == ("W"): | |
position = 0 - position | |
return position | |
while True: | |
gps_set_success = False # assume flightmode isn't set | |
GPS = serial.Serial('/dev/ttyAMA0', 9600, timeout=1) # open serial | |
print "serial opened" | |
GPS.flush() # wait for bytes to be physically read from the GPS | |
sendUBX(setNav, len(setNav)) # send command to enable flightmode | |
print "sendUBX_ACK function complete" | |
gps_set_success = getUBX_ACK(setNav) # check the flightmode is enabled | |
print "here is the current flightmode status:", gps_set_success | |
sendUBX(setNMEA_off, len(setNMEA_off)) # turn NMEA sentences off | |
GPS.close() # close the serial | |
print "serial port closed" | |
GPS.flush() | |
read_gps(gps_set_success) # run the read_gps function to get the data and parse it with status of flightmode |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment