Samples_UART_GPS_programming_old - gfd-dennou-club/mrubyc-esp32 GitHub Wiki
mrblib/loops/master.rb を以下のように編集して実行してみよ.この例では, GPS のデフォルトの出力を確認する.
1 # coding: utf-8 2 3 # GPS初期化 txPin = 17, rxPin = 16 のため uart_num = 2 とする 4 gps = UART.new(2, 9600) 5 6 # 出力をデフォルトに戻す 7 gps.write("$PMTK314,-1*04\r\n") 8 9 # 入力データをclear_tx_bufferで消去する 10 puts "> gps.clear_tx_buffer" 11 gps.clear_tx_buffer 12 13 # 入力データが来るのを待つ 14 sleep 2 15 16 # nonblock で到着している分のデータを取得する (デフォルトでは出力もされる) 17 lines = gps.read_nonblock(4096) 18 19 # 以下、到着したデータを 1 行ずつ読み込んで表示 20 while true 21 puts gps.gets() 22 sleep 1 23 end
コンパイルと実行. デフォルトでは大量のセンテンスが表示されることがわかる.
$ make flash monitor ...(前略)...... 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 .....(以下, 略).....
上記の mrblib/loops/master.rb の 7 行目を修正し,RMC のセンテンスのみ表示する.GPS に送信するコマンド (UART.write の引数) の詳細は,((<GPS のデータシート|URL:akizukidenshi.com/download/ds/taiyouyuden/GYSFDMAXB_spec_ae.pdf>)) を参照すること.
1 # coding: utf-8 2 3 # GPS初期化 txPin = 17, rxPin = 16 のため uart_num = 2 とする 4 gps = UART.new(2, 9600) 5 6 # 出力を RMS のみに 7 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") 8 9 # 入力データをclear_tx_bufferで消去する 10 puts "> gps.clear_tx_buffer" 11 gps.clear_tx_buffer 12 13 # 入力データが来るのを待つ 14 sleep 2 15 16 # nonblock で到着している分のデータを取得する (デフォルトでは出力もされる) 17 lines = gps.read_nonblock(4096) 18 19 # 以下、到着したデータを 1 行ずつ読み込んで表示 20 while true 21 puts gps.gets() 22 sleep 1 23 end
コンパイルと実行. RMS のセンテンスのみ出力されるようになったことが確認できる. タイミングの問題で欠損が生じる (取り出したデータサイズがゼロ) の場合も見られる.
$ make flash monitor ...(前略)...... 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 .....(以下, 略).....
上記の mrblib/loops/master.rb の 22 行目を修正し,10 秒間隔で UART.get してみる.
1 # coding: utf-8 2 3 # GPS初期化 txPin = 17, rxPin = 16 のため uart_num = 2 とする 4 gps = UART.new(2, 9600) 5 6 # 出力を RMS のみに 7 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") 8 9 # 入力データをclear_tx_bufferで消去する 10 puts "> gps.clear_tx_buffer" 11 gps.clear_tx_buffer 12 13 # 入力データが来るのを待つ 14 sleep 2 15 16 # nonblock で到着している分のデータを取得する (デフォルトでは出力もされる) 17 lines = gps.read_nonblock(4096) 18 19 # 以下、到着したデータを 1 行ずつ読み込んで表示 20 while true 21 puts gps.gets() 22 sleep 10 23 end
コンパイルと実行. 10 秒間隔で出力するようプログラミングしたつもりだが,第 2 引数の時刻部分を見ると 033932, 033933, 033934, 033935, 033936, … というように 1 秒間隔で表示される.これは GPS から受け取ったセンテンスはバッファに溜まっており,UART.get はバッファの最初の 1 行を読み出しているためである.
$ make flash monitor ...(前略)...... 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 .....(以下, 略).....
mrblib/loops/master.rb を編集し,バッファに溜まったセンテンスの最後の行を取り出して表示する. 具体的には,18 行目で UART.read_nonblock でバッファに入っているデータを全部取り出し,$ 区切りで配列化し,配列の最後の要素だけを pop メソッドで取り出すようにしている.
1 # coding: utf-8 2 3 # GPS初期化 txPin = 17, rxPin = 16 のため uart_num = 2 とする 4 gps = UART.new(2, 9600) 5 6 # 出力を RMC に限定する. 7 #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") 8 9 while true 10 11 # バッファをクリア 12 gps.clear_tx_buffer 13 14 # 2 秒間バッファに溜める 15 sleep 2 16 17 # データ取得・表示 18 line = gps.read_nonblock(4096).split('$').pop 19 puts "*** #{line} ***" 20 21 # 待ち 22 sleep 8 23 end
コンパイルと実行. UART.read_nonblock を用いると読み込んだデータが標準出力に表示され,さらに 19 行目の puts コマンドの出力が表示される.今度は先の例と異なり,10 秒間隔でデータが出力されていることが確認できる.なお, 先の例で示したように,GPS は 1 秒単位でデータを出力するが,タイミングの問題でマイコン側でデータの欠損が生じることがある.そのため,上記プログラムでは GPS からのデータの受け取りに 2 秒間費やしている.
$ make flash 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 .....(以下, 略).....
mrblib/loops/master.rb を編集し,日時と緯度経度を LCD への出力できるようにする.
1 # coding: utf-8 2 3 #I2C 初期化 4 i2c = I2C.new(22, 21) 5 6 # LCD 初期化 7 lcd = AQM0802A.new(i2c) 8 lcd.setup 9 10 # GPS初期化 txPin = 17, rxPin = 16 のため uart_num = 2 とする 11 gps = UART.new(2, 9600) 12 13 14 # 出力の調整 15 #gps.write("$PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28\r\n") # RMC と GGA 16 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") # RMC のみ 17 #gps.write("$PMTK314,-1*04\r\n") # デフォルト 18 19 20 while true 21 22 sleep 3 23 24 # バッファをクリア 25 gps.clear_tx_buffer 26 27 # 2 秒間バッファに溜める 28 sleep 2 29 30 # データ取得・表示 31 lines = gps.read_nonblock(4096).split('$').pop 32 data = lines.split(',') #カンマ区切りで配列化 33 34 if data[2] == "A" && data.size == 13 #ステータスが "A" であること,データ数が揃っていることを確認. 35 # data[9] : 日付, data[1] : 時刻 36 time1 = "#{data[9][4]}#{data[9][5]}-#{data[9][2]}#{data[9][3]}-#{data[9][0]}#{data[9][1]}" 37 time2 = "#{data[1][0]}#{data[1][1]}:#{data[1][2]}#{data[1][3]}:#{data[1][4]}#{data[1][5]}" 38 lat = "#{data[3].to_f / 100.0}#{data[4]}" 39 lng = "#{data[5].to_f / 100.0}#{data[6]}" 40 41 puts "time (UTC): #{time1}T#{time2}" 42 puts "Latitude: #{lat}" 43 puts "Longitude: #{lng}" 44 45 lcd.clear 46 lcd.cursor(0, 0) 47 lcd.write_string(time1) 48 lcd.cursor(0, 1) 49 lcd.write_string(time2) 50 sleep 5 51 lcd.cursor(0, 0) 52 lcd.write_string(lat) 53 lcd.cursor(0, 1) 54 lcd.write_string(lng) 55 56 else 57 lcd.clear 58 lcd.cursor(0, 0) 59 lcd.write_string("Please") 60 lcd.cursor(1, 1) 61 lcd.write_string("Wait...") 62 end 63 64 end
コンパイルと実行. 10 秒ごとに標準出力に日時と緯度経度が表示され,さらに LCD にも同じものが表示されることが確認できる.
$ make flash monitor ...(前略)...... start I2C (mruby/c class) start UART (mruby/c class) start AQM0802A (mruby/c class) UART: driver was successfully installed $GPRMC,042027.000,A,3529.8215,N,13301.5004,E,0.45,36.80,190621,,,A*5E $GPRMC,042028.000,A,3529.8215,N,13301.5003,E,0.29,36.80,190621,,,A*5C time (UTC): 21-06-19T04:20:28 Latitude: 35.2982N Longitude: 133.015E $GPRMC,042037.000,A,3529.8223,N,13301.4984,E,0.77,357.23,190621,,,A*66 $GPRMC,042038.000,A,3529.8227,N,13301.4974,E,0.76,1.14,190621,,,A*67 time (UTC): 21-06-19T04:20:38 Latitude: 35.2982N Longitude: 133.015E A*6D 0.79,342.58,190621,,,A*62 データ欠損 $GPRMC,042049.000,A,3529.8255,N,13301.4943,E,0.83,347.63,190621,,,A*6B time (UTC): 21-06-19T04:20:49 Latitude: 35.2983N Longitude: 133.015E $GPRMC,042058.000,A,3529.8255,N,13301.4940,E,0.62,294.92,190621,,,A*66 $GPRMC,042059.000,A,3529.8249,N,13301.4935,E,0.59,294.92,190621,,,A*60 time (UTC): 21-06-19T04:20:59 Latitude: 35.2982N Longitude: 133.015E .....(以下, 略).....
### サンプル (2)
# GPS初期化 txPin = 17, rxPin = 16 のため uart_num = 2 とする
gps = UART.new(2, 9600)
# 出力を RMC に限定する.
#gps.write("$PMTK314,-1*04\r\n")
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
# バッファをクリア
gps.clear_tx_buffer
# 3 秒間バッファに溜める
sleep 3
# データ取得・表示
lines = gps.read_nonblock(4096).split('$')
while true
line = lines.pop.split(',')
if line[0] == "GPRMC"
puts "*** #{line} ***"
puts "*** STATUS : #{line[2]} ***"
if line[2] == "A" && line.size == 13
puts "*** LAT : #{line[3]} #{line[4]} ***"
puts "*** LNG : #{line[5]} #{line[6]} ***"
year = "20#{line[9][4]}#{line[9][5]}"
mon = "#{line[9][2]}#{line[9][3]}"
day = "#{line[9][0]}#{line[9][1]}"
hour = "#{line[1][0]}#{line[1][1]}"
min = "#{line[1][2]}#{line[1][3]}"
sec = "#{line[1][4]}#{line[1][5]}"
puts "*** TIME : #{year}-#{mon}-#{day} #{hour}:#{min}:#{sec} UTC ***"
end
break
end
end
sleep 8
end