2
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ラズパイでGPSモジュール(AE-GYSFDMAXB)を使う方法

Last updated at Posted at 2021-12-14

目次

開発環境

RaspberryPi Zero W
OS : 2021-05-07-raspios-buster-armhf
python 2系(3系に対応しているコードもすぐに載せる予定)

ラズパイへの接続方法

配線

Raspberry PiはUART通信用のピンを備えています
UARTとは、マイコン間で主に使用される通信方式の一つです
AE-GYSFDMAXBはUART通信で情報をやり取りできるので、Raspberry PiとAE-GYSFDMAXBをUART通信できるように接続します

RaspberryPi GPSモジュール
5V 5V
GND GND
RxD TxD
TxD RxD
なし 1PPS
RxDとTxDはクロスさせて接続することに注意しましょう

シリアルの有効化

sudo raspi-config
からP5 Interfacing Options→P6 Serial

> ls /dev/serial*
/dev/serial0

/dev/serial0があることを確認

コンソールをserial0からtty1へ変更

sudo nano /boot/cmdline.txt
もとの/boot/cmdline.txtから、console=serial0,115200の記述を削除する
変更後はこんな感じ

dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait quiet splash plymouth.ignore-serial-consoles

終わったら再起動
sudo reboot

コードの動かし方

$ python2 wpi3_GPS.py
※初めてコードを動かす場合5分程度ラズパイを放置する必要があります
※屋根のない外で動作させる必要があります

コード

wpi3_GPS.py
#!/usr/local/bin/python
# -*- coding: utf-8 -*-

import serial
import datetime
import os

ser = serial.Serial(               #みちびき対応GPS用の設定
  port = "/dev/ttyS0",           #シリアル通信を用いる
  baudrate = 9600,                 #baudレート
  parity = serial.PARITY_NONE,     #パリティ
  bytesize = serial.EIGHTBITS,     #データのビット数
  stopbits = serial.STOPBITS_ONE,  #ストップビット数
  timeout = None,                  #タイムアウト値
  xonxoff = 0,                     #ソフトウェアフロー制御
  rtscts = 0,                      #RTS/CTSフロー制御
  )

#後で使う変数をあらかじめ宣言
alt_lat_long = '0,0,0'     #GPSから得られる、高度、緯度、経度の情報
num_sat = '0'   #GPSから得られる、衛星の個数の情報

def sixty_to_ten(x):
  ans = float(int(x) + ((x - int(x)))*100/60)
  return ans

if __name__ == "__main__":

  #GGA用のファイル初期化
  f = open('datagga.csv','w')
  f.write('yyyy-mm-dd HH:MM:SS.ffffff ,a number of satellites ,high ,latitude ,longitude \n')  #出力フォーマット
  f.close()

  #GSV用のファイル初期化
  f = open('datagsv.csv','w')
  f.write('No. ,Elevation in degrees ,degrees in true north \n') #仰角と方位角
  f.close()

  now = datetime.datetime.now()
  if os.path.exists("datagga.csv"):
    new_name = "{0}_{1:%Y%m%d-%H%M%S}.{2}".format("datagga",now,"csv")
    os.rename("datagga.csv",new_name)

  #出力フォーマット
  print ("yyyy-mm-dd HH:MM:SS.ffffff ,a number of satellites ,high ,latitude ,longitude")
  print ("No. ,Elevation in degrees ,degrees in true north \n")
  ##############################################################################
  while True:
    gps_data = ser.readline()  #1行ごとに読み込み、処理を繰り返す
    if not gps_data:
      print("no data")
    #GGA GPSセンサの位置情報を知る
    #$GPGGA,UTC時刻,緯度,緯度の南北,経度,経度の東西,位置特定品質,使用衛星数,
    #水平精度低下率,海抜高さ,高さの単位,ジオイド高さ,高さの単位,DGPS,差動基準地点
    if (gps_data.startswith('$GPGGA')): #startswith:1行の先頭文字を検索する
      gpgga = (gps_data.split(",")) #split:1行をカンマで区切って変数にlist型で保存
      #緯度と経度の情報を、listからfloatに直す
      if gpgga[2]:
        lat_60,long_60,altitude = float(gpgga[2]),float(gpgga[4]),float(gpgga[9])
      else:
        lat_60,long_60,altitude = 0,0,0    #緯度の情報が無い
      #緯度と経度を60進法から10進法に変換、東経と北緯で計算
      if gpgga[3] == "W":  lat_60 *= -1
      if gpgga[5] == "S":  long_60 *= -1
      lat_10,long_10 = sixty_to_ten(lat_60/100),sixty_to_ten(long_60/100)
      #csv形式で出力する用のデータを変数にまとめて保存する(なければ0とする)
      alt_lat_long = "%3.2f,%5.6f,%5.6f" % (altitude,lat_10,long_10) if gpgga[9] else "0,0,0" #高度、緯度、経度
      print(alt_lat_long)
###############
    #GSA 特定タイプを見ることでGPSの通信状況を確認する
    #$GPGSA,UTC時刻,特定タイプ,衛星番号,精度低下率(位置、水平、垂直)
    #if (gps_data.startswith('$GPGSA')):  print gps_data, #特定タイプ(2D,3D等)を確認するために表示。3の時が良好。
###############
    #GSV 受信した衛星の位置等の情報を記録する
    #$GPGSV,UTC時刻,総センテンス数,このセンテンスの番号,総衛星数,
    #衛星番号,衛星仰角,衛星方位角,キャリア/ノイズ比, を繰り返す
    if (gps_data.startswith('$GPGSV')):
      f = open('datagsv.csv','a')
      gpgsv = (gps_data.split(','))
      #衛星の個数を記録し、情報を追加する
      if (gpgsv[2] == '1'):
        num_sat = gpgsv[3]
        f.write(gpgsv[1] + gpgsv[3] + '\n')
      #それぞれの衛星の番号、仰角、方位角を追加する
      if (len(gpgsv) == 4):  num_sat = '0'
      elif (len(gpgsv) >= 8):
        gsv1 =  gpgsv[4] + gpgsv[5] + gpgsv[6]   #センテンス中一つ目の衛星
        f.write(gsv1 + '\n')
      elif (len(gpgsv) >= 12):
        gsv2 =  gpgsv[8] + gpgsv[9] + gpgsv[10]  #二つ目の衛星
        f.write(gsv2 + '\n')
      elif (len(gpgsv) >= 16):
        gsv3 =  gpgsv[12] + gpgsv[13] + gpgsv[14]#三つ目の衛星
        f.write(gsv3 + '\n')
      elif (len(gpgsv) == 20):
        gsv4 =  gpgsv[16] + gpgsv[17] + gpgsv[18]#四つ目の衛星
        f.write(gsv4 + '\n')
      f.close()
#############
    #ZDA NMEA出力における最後の行のため、時間を調べつつ一括ファイル出力する
    #$GPZDA,UTC時刻(hhmmss.mm),日,月,西暦,時,分,
    if (gps_data.startswith('$GPZDA')):
      gpzda = (gps_data.split(","))
      #GPSで取得したUTCの日付を保存する
      yyyymmddhhmmssff = datetime.datetime.strptime(gpzda[4] + '/' + gpzda[3] + '/' + gpzda[2] + ' ' + gpzda[1],"%Y/%m/%d %H%M%S.%f")
      time_and_number = "%s,%s" % (yyyymmddhhmmssff,num_sat)
      #ファイル名を書き換える
      #GGAのデータを標準出力、加えてcsvファイルに出力
      f = open(new_name,'a')
      f.write(time_and_number + ',' + alt_lat_long + '\n')
      print(time_and_number + ',' + alt_lat_long)
      f.close()

main関数の解説

取得したデータはdatagga_{日時}.csvに出力されます

応用

移動した距離の測定(緯度、経度によって1度あたりの距離が変わることに注意)
指定した緯度経度へ移動など
いろいろ

2
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?