I have a USB receiver at hand, so I'll attach it to a Raspberry Pi to get my current location. [BU-353S4](https://www.amazon.co.jp/GlobalSat-BU-353S4-GLOBALSAT-BU-353S4-SiRFstarIV%E6%90%AD%E8%BC%89-GPS%E3%83% AC% E3% 82% B7% E3% 83% BC% E3% 83% 90USB-% E6% 9D% B1% E4% BA% AC% E9% 80% 9A% E5% 95% 86% E6% AD% A3 % E8% A6% 8F% E8% B2% A9% E5% A3% B2 / dp / B00HZCQYLU) was used.
Although it is an analog method, execute the following command before and after inserting and removing the GPS receiver to identify the target device.
$ ls /dev/ttyUSB*
/dev/ttyUSB0 /dev/ttyUSB1 /dev/ttyUSB2 /dev/ttyUSB3 /dev/ttyUSB4
This time, we will proceed on the assumption that it is recognized as / dev / ttyUSB4
.
gps.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import time
import serial
#Device specification
DEV = '/dev/ttyUSB4'
#Latitude and longitude fractional notation ⇒ conversion function to frequency notation
def convert(x):
result = (float(x[0:-7])+(float(x[-7:])/60))
return result
#A function that returns the required value as a string
def get_str(x):
result =""
if (x[2] == "A") and (x[2] != ""):
result += "state:"+"ok "
elif (x[2] == "V") and (x[2] != ""):
result += "state:"+"alert "
else:
result += "state:"+"no data "
if x[7] != "":
result += 'speed:'+ '%.1f' % (float(x[7])*1.852) + "km/h "
else:
result += "speed:"+"no data "
if (x[4] == "N") and ( x[4] != "" ):
result += "north latitude:" + '%.4f' % convert(x[3]) +' '
elif (x[4] == "S") and ( x[4] != "" ):
result += "south latitude:" + '%.4f' % convert(x[3]) +' '
else:
result += "latitude:"+"no data "
if (x[6] == "E") and ( x[6] != ""):
result += "east longitude:" + '%.4f' % convert(x[5]) +' '
elif (x[6] == "W") and ( x[6] != ""):
result += "west longitude" + '%.4f' % convert(x[5]) +' '
else:
result += "logitude:"+"no data "
return result
#Checksum verification
def checksum_verify(c_sum,data):
c_data = '0x00'
for i in range(1,len(data)-3):
c_data = hex(int(c_data,16) ^ int(hex(ord(data[i])),16))
if int(c_sum,16) == int(c_data,16):
return True
else:
return False
#Main loop
#Process only the GPRMC value, do not process if the number of elements of that value is less than 13 and it is not acquired well
try:
#Get serial
sr = serial.Serial(DEV, 4800)
while 1:
#Line feed code excluded
tmp = sr.readline().rstrip()
#Checksum confirmation
if checksum_verify(tmp[-2:],tmp):
tmp2 = tmp.split(",")
#Process only GPRMC
if (tmp2[0] == '$GPRMC'):
line = get_str(tmp2)
print 'OK:'+tmp
print line
time.sleep(0.5)
else:
print 'NG:'+tmp
finally:
print 'serial_close'
sr.close()
Each value of GPRMC is as follows
tmp2[1]UTC time Japan standard time-9 hours
tmp2[2]Status A is normal V is warning
tmp2[3]latitude(Fractional notation)
tmp2[4](N)North latitude(S)South latitude
tmp2[5]longitude(Fractional notation)
tmp2[6](E)East(W)Is it Nishikei?
tmp2[7]Movement speed knot
tmp2[8]True bearing
tmp2[9]Coordinated Universal Time(UTC)ddmmyy format
tmp2[12]Checksum
※Moving Speed knot is 1.852 times and km / h
※Checksum
XOR the characters between $
to *
and check if they are the same value
$GPRMC,034357.279,V,,,,,,,020117,,,N*42
If above,
GPRMC,034357.279,V,,,,,,,020117,,,N
Is the calculation target
It is inconvenient that it changes to / dev / ttyUSB0
or / dev / ttyUSB4
each time depending on the connected device and environment.
It cannot be used in the auto-start script. It is a countermeasure in such a case.
If you have decided which USB port to plug in, check the information below and use it.
$ ls -al /dev/serial/by-path
total 0
drwxr-xr-x 2 root root 140 Jan 2 01:30 .
drwxr-xr-x 4 root root 80 Jan 1 20:03 ..
lrwxrwxrwx 1 root root 13 Jan 2 01:30 platform-3f980000.usb-usb-0:1.3:1.0-port0 -> ../../ttyUSB4
lrwxrwxrwx 1 root root 13 Jan 1 20:03 platform-3f980000.usb-usb-0:1.4:1.0-port0 -> ../../ttyUSB0
lrwxrwxrwx 1 root root 13 Jan 1 20:03 platform-3f980000.usb-usb-0:1.4:1.1-port0 -> ../../ttyUSB1
lrwxrwxrwx 1 root root 13 Jan 1 20:03 platform-3f980000.usb-usb-0:1.4:1.2-port0 -> ../../ttyUSB2
lrwxrwxrwx 1 root root 13 Jan 1 20:03 platform-3f980000.usb-usb-0:1.4:1.3-port0 -> ../../ttyUSB3
If the target device is / dev / ttyUSB4
, fix it as follows
#Device specification
DEV = '/dev/ttyUSB4'
↓
DEV = '/dev/serial/by-path/platform-3f980000.usb-usb-0:1.3:1.0-port0'
See Oracle's About udev rules for udev` rules.
Execute the following command to check the information (when / dev / ttyUSB4
is the target device)
udevadm info -a -p $(sudo udevadm info -q path -n /dev/ttyUSB4)
Check the following from the displayed
looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.3':
KERNELS=="1-1.3"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bDeviceProtocol}=="00"
ATTRS{devpath}=="1.3"
ATTRS{idVendor}=="067b"
ATTRS{speed}=="12"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bConfigurationValue}=="1"
ATTRS{bMaxPacketSize0}=="64"
ATTRS{busnum}=="1"
ATTRS{devnum}=="21"
ATTRS{configuration}==""
ATTRS{bMaxPower}=="100mA"
ATTRS{authorized}=="1"
ATTRS{bmAttributes}=="80"
ATTRS{bNumConfigurations}=="1"
ATTRS{maxchild}=="0"
ATTRS{bcdDevice}=="0400"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{quirks}=="0x0"
ATTRS{version}==" 1.10"
ATTRS{urbnum}=="65169"
ATTRS{ltm_capable}=="no"
ATTRS{manufacturer}=="Prolific Technology Inc. "
ATTRS{removable}=="removable"
ATTRS{idProduct}=="2303"
ATTRS{bDeviceClass}=="00"
ATTRS{product}=="USB-Serial Controller D"
Extract the following three points
ATTRS{idProduct}=="2303"
ATTRS{idVendor}=="067b"
ATTRS{product}=="USB-Serial Controller D"
Create a file such as 70-bu353s4.rules
under /etc/udev/rules.d
and enter the following information.
/etc/udev/rules.d
and they are duplicated, specify a unique number.70-bu353s4.rules
ATTRS{idProduct}=="2303",ATTRS{idVendor}=="067b",ATTRS{product}=="USB-Serial Controller D",SYMLINK+="bu353s4"
After creating the file, insert and remove the GPS receiver
Now you can connect to the GPS receiver with / dev / bu353s4
, so fix it as follows
#Device specification
DEV = '/dev/ttyUSB4'
↓
DEV = '/dev/bu353s4'
Recommended Posts