Skip to content

Samples_UART_GPS_programming

Ko-ichiro Sugiyama edited this page May 28, 2023 · 5 revisions

GPS プログラミング (step by step)

プログラム例と実行 (1)

GPS のデフォルトの出力の確認

# GPSの電源を入れる (高専ボードの場合に必要)
gps_pw = GPIO.new(5, GPIO::OUT)
gps_pw.write(0)

# GPS初期化 txPin = 17, rxPin = 16 のため uart_num = 2 とする
gps = UART.new(2, 9600)

# 出力をデフォルトに戻す
gps.write("$PMTK314,-1*04\r\n")

# 入力データをclear_tx_bufferで消去する
puts "> gps.clear_tx_buffer"
gps.clear_tx_buffer

# 入力データが来るのを待つ
sleep 2

# nonblock で到着している分のデータを取得する (デフォルトでは出力もされる)
lines = gps.read_nonblock(4096)

# 以下、到着したデータを 1 行ずつ読み込んで表示
while true
  puts  gps.gets()
  sleep 1
end

実行すると,大量のセンテンスが表示されることがわかる.

     ...(前略)......
     UART: driver was successfully installed
     > gps.clear_tx_buffer
     )?38
     $GPZDA,032458.000,19,06,2021,,*51
     $GPGGA,032459.000,3529.8110,N,13301.4898,E,1,6,4.45,40.2,M,28.6,M,,*64
     $GPGLL,3529.8110,N,13301.4898,E,032459.000,A,A*58
     $GPGSA,A,3,28,21,01,14,17,19,,,,,,,4.54,4.45,0.93*0B
     $GPGSV,4,1,15,14,62,296,28,01,60,029,14,22,54,084,,03,53,135,*78
     $GPGSV,4,2,15,28,45,312,30,21,39,046,20,17,38,307,31,08,22,095,*75
     $GPGSV,4,3,15,30,19,235,,19,14,293,21,07,05,201,,06,03,240,*71
     $GPGSV,4,4,15,193,,,,194,,,,195,,,*47
     $GPRMC,032459.000,A,3529.8110,N,13301.4898,E,0.18,217.89,190621,,,A*6E
     $GPVTG,217.89,T,,M,0.18,N,0.33,K,A*31
     $GPZDA,032459.000,19,06,2021,,*50
     $GPGGA,032500.000,3529.8107,N,13301.4903,E,1,6,4.45,40.3,M,28.6,M,,*6D
     $GPGLL,3529.8107,N,13301.4903,E,032500.000,A,A*50
     $GPGSA,A,3,28,21,01,14,17,19,,,,,,,4.54,4.45,0.93*0B
     $GPGSV,4,1,15,14,62,296,28,01,60,029,13,22,54,084,,03,53,135,*7F
     $GPGSV,4,2,15,28,45,312,30,21,39,046,20,17,38,307,31,08,22,095,*75
     $GPGSV,4,3,15,30,19,235,,19,14,293,21,07,05,201,,06,03,240,*71
     .....(以下, 略).....

プログラム例と実行 (2)

上記の src/master.rb の 9 行目を修正し,RMC のセンテンスのみ表示する. GPS に送信するコマンド (UART.write の引数) の詳細は, ((<GPS のデータシート|URL:https://akizukidenshi.com/download/ds/taiyouyuden/GYSFDMAXB_spec_ae.pdf>)) を参照すること.

# GPSの電源を入れる (高専ボードの場合に必要)
gps_pw = GPIO.new(5, GPIO::OUT)
gps_pw.write(0)

# GPS初期化 txPin = 17, rxPin = 16 のため uart_num = 2 とする
gps = UART.new(2, 9600)

# 出力を RMS のみに
sleep 1
gps.write("$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29\r\n")

# 入力データをclear_tx_bufferで消去する
puts "> gps.clear_tx_buffer"
gps.clear_tx_buffer

# 入力データが来るのを待つ
sleep 2

# nonblock で到着している分のデータを取得する (デフォルトでは出力もされる)
lines = gps.read_nonblock(4096)

# 以下、到着したデータを 1 行ずつ読み込んで表示
while true
  puts  gps.gets()
  sleep 1
end

実行すると RMS のセンテンスのみ出力されるようになったことが確認できる. タイミングの問題で欠損が生じる (取り出したデータサイズがゼロ) の場合も見られる.

     ...(前略)......
     start UART (mruby/c class)
     start AQM0802A (mruby/c class)
     start RC8035SA (mruby/c class)
     UART: driver was successfully installed
     > gps.clear_tx_buffer
     ???b*?1,6,3.71,48.0,M,28.6,M,,*6B
     $GPGLL,3529.8205,N,13301.5026,E,033250.000,A,A*5D
     $GPGSA,A,3,28,01,14,17,21,19,,,,,,,3.83,3.71,0.94*01
     $GPGSV,4,1,15,14,64,290,24,01,57,032,18,03,56,129,,22,53,078,13*78
     $GPGSV,4,2,15,28,48,309,31,17,40,310,25,21,37,048,19,08,20,098,*7A
     $GPGSV,4,3,15,19,17,295,30,30,16,232,,06,05,242,,07,03,199,*7C
     $GPGSV,4,4,15,193,,,,194,,,,195,,,*47
     $GPRMC,033250.000,A,3529.8205,N,13301.5026,E,0.92,196.34,190621,,,A*65
     $GPVTG,196.34,T,,M,0.92,N,1.71,K,A*38
     $GPZDA,033250.000,19,06,2021,,*5E
     $PMTK001,314,3*36
     $GPRMC,033251.000,A,3529.8199,N,13301.5026,E,1.17,198.50,190621,,,A*62
                                                                              欠損
     $GPRMC,033252.000,A,3529.8198,N,13301.5029,E,0.60,189.15,190621,,,A*6F
     $GPRMC,033253.000,A,3529.8198,N,13301.5027,E,0.59,189.15,190621,,,A*6A
     $GPRMC,033254.000,A,3529.8201,N,13301.5026,E,0.13,189.15,190621,,,A*61
     $GPRMC,033255.000,A,3529.8202,N,13301.5023,E,0.38,189.15,190621,,,A*6F
     $GPRMC,033256.000,A,3529.8204,N,13301.5021,E,0.11,189.15,190621,,,A*63
     $GPRMC,033257.000,A,3529.8204,N,13301.5021,E,0.30,189.15,190621,,,A*61
     $GPRMC,033258.000,A,3529.8204,N,13301.5020,E,0.35,189.15,190621,,,A*6A
     $GPRMC,033259.000,A,3529.8204,N,13301.5019,E,0.51,189.15,190621,,,A*63
     $GPRMC,033300.000,A,3529.8204,N,13301.5017,E,0.65,222.88,190621,,,A*61
     .....(以下, 略).....

プログラム例と実行 (3)

上記の src/master.rb を修正し,10 秒間隔で UART.get してみる.

# GPSの電源を入れる (高専ボードの場合に必要)
gps_pw = GPIO.new(5, GPIO::OUT)
gps_pw.write(0)

# GPS初期化 txPin = 17, rxPin = 16 のため uart_num = 2 とする
gps = UART.new(2, 9600)

# 出力を RMS のみに
sleep 1
gps.write("$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29\r\n")

# 入力データをclear_tx_bufferで消去する
puts "> gps.clear_tx_buffer"
gps.clear_tx_buffer

# 入力データが来るのを待つ
sleep 2

# nonblock で到着している分のデータを取得する (デフォルトでは出力もされる)
lines = gps.read_nonblock(4096)

# 以下、到着したデータを 1 行ずつ読み込んで表示
while true
  puts  gps.gets()
  sleep 10
end

実行結果の第 2 引数 (時刻) を見ると 033932, 033933, 033934, 033935, 033936, ... というように 1 秒間隔で表示されていることがわかる.10秒間隔ではない. これは GPS から受け取ったセンテンスはバッファに溜まっており,UART.get はバッファの最初の 1 行を読み出しているためである.

     ...(前略)......
     UART: driver was successfully installed
     > gps.clear_tx_buffer
     $PMTK001,314,3*36
     $GPRMC,033932.000,A,3529.8222,N,13301.5116,E,0.14,162.49,190621,,,A*62
     $GPRMC,033933.000,A,3529.8221,N,13301.5116,E,0.32,162.49,190621,,,A*64
     $GPRMC,033934.000,A,3529.8220,N,13301.5117,E,0.62,165.37,190621,,,A*68
     $GPRMC,033935.000,A,3529.8210,N,13301.5114,E,0.63,166.90,190621,,,A*66
     $GPRMC,033936.000,A,3529.8201,N,13301.5112,E,0.83,188.62,190621,,,A*60
     .....(以下, 略).....

プログラム例と実行 (4)

バッファに溜まったセンテンスの最後の行を取り出して表示する. 具体的には,UART.read_nonblock でバッファに入っているデータを全部取り出し, $ 区切りで配列化し,配列の最後の要素だけを pop メソッドで取り出すようにしている.

# GPSの電源を入れる (高専ボードの場合に必要)
gps_pw = GPIO.new(5, GPIO::OUT)
gps_pw.write(0)

# GPS初期化 txPin = 17, rxPin = 16 のため uart_num = 2 とする
gps = UART.new(2, 9600)

# 出力を RMS のみに
sleep 1
gps.write("$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29\r\n")

while true

  # 入力データをclear_tx_bufferで消去する
  gps.clear_tx_buffer

  # 入力データが来るのを待つ
  sleep 2

  # データ取得・表示
  lines = gps.read_nonblock(4096).split('$').pop
  puts "*** #{lines} ***"

  # 待ち
  sleep 8
end

実行すると,UART.read_nonblock を用いると読み込んだデータが標準出力に表示され, さらに puts コマンドの出力が表示される. 今度は先の例と異なり,10 秒間隔でデータが出力されていることが確認できる. なお, 先の例で示したように,GPS は 1 秒単位でデータを出力するが, タイミングの問題でマイコン側でデータの欠損が生じることがある. そのため,上記プログラムでは GPS からのデータの受け取りに 2 秒間費やしている.

   $ make spiffs  spiffs-monitor

     ...(前略)......
     start RC8035SA (mruby/c class)
     UART: driver was successfully installed
     $GPRMC,040618.000,A,3529.8208,N,13301.5070,E,0.70,217.33,190621,,,A*66
     $GPRMC,040619.000,A,3529.8205,N,13301.5070,E,0.62,217.33,190621,,,A*69
      ***GPRMC,040619.000,A,3529.8205,N,13301.5070,E,0.62,217.33,190621,,,A*69
     $GPRMC,040628.000,A,3529.8207,N,13301.5068,E,0.38,217.33,190621,,,A*6F
     $GPRMC,040629.000,A,3529.8206,N,13301.5069,E,0.44,217.33,190621,,,A*65
      ***GPRMC,040629.000,A,3529.8206,N,13301.5069,E,0.44,217.33,190621,,,A*65
     0638.000,A,3529.8192,N,13301.5068,E,0.07,186.15,190621,,,A*62                データ欠損
     $GPRMC,040639.000,A,3529.8192,N,13301.5068,E,0.28,186.15,190621,,,A*6E
      ***GPRMC,040639.000,A,3529.8192,N,13301.5068,E,0.28,186.15,190621,,,A*6E
     ,3529.8191,N,13301.5072,E,0.17,186.20,190621,,,A*6A                          データ欠損
     $GPRMC,040649.000,A,3529.8191,N,13301.5073,E,0.52,186.20,190621,,,A*6B
      ***GPRMC,040649.000,A,3529.8191,N,13301.5073,E,0.52,186.20,190621,,,A*6B
     090,E,0.27,66.62,190621,,,A*52                                               データ欠損
     $GPRMC,040659.000,A,3529.8205,N,13301.5091,E,0.11,66.62,190621,,,A*56
      ***GPRMC,040659.000,A,3529.8205,N,13301.5091,E,0.11,66.62,190621,,,A*56
     190621,,,A*62                                                                データ欠損
     $GPRMC,040709.000,A,3529.8206,N,13301.5109,E,0.39,107.08,190621,,,A*61
     ***GPRMC,040709.000,A,3529.8206,N,13301.5109,E,0.39,107.08,190621,,,A*61
     .....(以下, 略).....
Clone this wiki locally