Luat Air780E/Air700E使用定位模塊獲取設備經緯度
來自星星筆記(cxing.top):鏈接先左鍵選中再右鍵點擊打開(直接復制打開可能打不開)??https://cxing.top/archives/34.html

先來代碼
-- LuaTools需要PROJECT和VERSION這兩個信息
PROJECT = "uart_gps"
VERSION = "1.0.0"
log.info("main", PROJECT, VERSION)
-- 引入必要的庫文件(lua編寫), 內部庫不需要require
sys = require("sys")
if wdt then
? ? --添加硬狗防止程序卡死,在支持的設備上啟用這個功能
? ? wdt.init(9000)--初始化watchdog設置為9s
? ? sys.timerLoopStart(wdt.feed, 3000)--3s喂一次狗
end
log.info("main", "uart demo")
local uartid = 2 -- 根據(jù)實際設備選取不同的uartid
--初始化
local result = uart.setup(
? ? uartid,--串口id
? ? 9600,--波特率
? ? 8,--數(shù)據(jù)位
? ? 1--停止位
)
-- 收取數(shù)據(jù)會觸發(fā)回調, 這里的"receive" 是固定值
uart.on(uartid, "receive", function(id, len)
? ? local s = ""
? ? repeat
? ? ? ? -- 如果是air302, len不可信, 傳1024
? ? ? ? -- s = uart.read(id, 1024)
? ? ? ? s = uart.read(id, len)
? ? ? ? if #s > 0 then -- #s 是取字符串的長度
? ? ? ? ? ? -- log.info("uart", "receive", id, #s, s)
? ? ? ? ? ? local utc_time, lat, lat_ns, lon, lon_ew = string.match(s, "%$GNGGA,(%d+%.%d+),(%d+%.%d+),(%a),(%d+%.%d+),(%a),")
? ? ? ? ? ? if utc_time and lat and lat_ns and lon and lon_ew then
? ? ? ? ? ? ? ? log.info("uart", "UTC Time", utc_time)
? ? ? ? ? ? ? ? local hour = tonumber(utc_time:sub(1,2))
? ? ? ? ? ? ? ? local minute = tonumber(utc_time:sub(3,4))
? ? ? ? ? ? ? ? local second = tonumber(utc_time:sub(5,6))
? ? ? ? ? ? ? ? hour = hour +8
? ? ? ? ? ? ? ? if hour >=24 then
? ? ? ? ? ? ? ? ? ? hour = hour -24
? ? ? ? ? ? ? ? end
? ? ? ? ? ? ? ? local time_str = string.format("%02d:%02d:%02d", hour, minute, second) -- 轉換為時分秒格式
? ? ? ? ? ? ? ? log.info("uart", "Beijing Time", time_str)
? ? ? ? ? ? ? ? -- 轉換經緯度為GPS坐標格式
? ? ? ? ? ? ? ? local lat_deg = math.floor(tonumber(lat) / 100)
? ? ? ? ? ? ? ? local lat_min = tonumber(lat) % 100
? ? ? ? ? ? ? ? local lat_google = lat_deg + lat_min / 60
? ? ? ? ? ? ? ? if lat_ns == "S" then
? ? ? ? ? ? ? ? ? ? lat_google = -lat_google
? ? ? ? ? ? ? ? end
? ? ? ? ? ? ? ? log.info("uart", "Latitude", lat_google)
? ? ? ? ? ? ? ? local lon_deg = math.floor(tonumber(lon) / 100)
? ? ? ? ? ? ? ? local lon_min = tonumber(lon) % 100
? ? ? ? ? ? ? ? local lon_google = lon_deg + lon_min / 60
? ? ? ? ? ? ? ? if lon_ew == "W" then
? ? ? ? ? ? ? ? ? ? lon_google = -lon_google
? ? ? ? ? ? ? ? end
? ? ? ? ? ? ? ? log.info("uart", "Longitude", lon_google)
? ? ? ? ? ? end
? ? ? ? end
? ? ? ? if #s == len then
? ? ? ? ? ? break
? ? ? ? end
? ? until s == ""
end)
-- 用戶代碼已結束---------------------------------------------
-- 結尾總是這一句
sys.run()
-- sys.run()之后后面不要加任何語句!!!!!
代碼解釋
這段代碼實現(xiàn)了通過UART串口讀取GPS模塊發(fā)送的數(shù)據(jù),并對數(shù)據(jù)進行解析和處理,最終輸出解析后的結果。具體解釋如下:
1、設置項目名稱和版本號:
首先通過 PROJECT 和 VERSION 變量分別設置了項目名稱和版本號。
2、輸出項目名稱和版本號:
使用 log.info() 函數(shù)輸出項目名稱和版本號。
3、引入必要的庫文件:
使用 require() 函數(shù)引入了系統(tǒng)庫 sys,用于后續(xù)的定時器操作和系統(tǒng)運行。
4、如果硬件支持硬狗,初始化并啟用硬狗功能:
檢查系統(tǒng)是否支持硬狗,如果支持則通過 wdt.init() 函數(shù)初始化硬狗并設置喂狗時間,通過 sys.timerLoopStart() 函數(shù)循環(huán)定時喂狗,以避免程序卡死等異常情況。
5、輸出提示信息:
使用 log.info() 函數(shù)輸出提示信息,表示進入了GPS數(shù)據(jù)讀取和處理的代碼段。
6、設置UART串口ID:
通過 uartid 變量設置了UART串口的ID,這里設置為2。
7、初始化UART串口:
使用 uart.setup() 函數(shù)初始化UART串口,設置波特率為9600,數(shù)據(jù)位為8位,停止位為1位。
8、注冊UART串口數(shù)據(jù)接收回調函數(shù):
使用 uart.on() 函數(shù)注冊UART串口數(shù)據(jù)接收回調函數(shù),當串口接收到數(shù)據(jù)時會自動觸發(fā)回調函數(shù),并將接收到的數(shù)據(jù)長度作為參數(shù)傳入回調函數(shù)。
9、處理UART串口接收到的數(shù)據(jù):
在回調函數(shù)中,使用 uart.read() 函數(shù)循環(huán)讀取串口數(shù)據(jù),并使用 string.match() 函數(shù)對讀取到的數(shù)據(jù)進行正則匹配,提取出其中的經緯度和時間等信息,然后進行格式轉換和計算,并使用 log.info() 函數(shù)輸出解析后的信息。
10、最后,運行代碼:
通過 sys.run() 函數(shù)啟動系統(tǒng)運行,讓代碼可以正常執(zhí)行。
重點代碼解釋
1、定位模塊輸出(波特率為9600):
```c
$GNGGA,084852.000,2236.9453,N,11408.4790,E,1,05,3.1,89.7,M,0.0,M,,*48
$GNGLL,2236.9453,N,11408.4790,E,084852.000,A,A*4C
$GPGSA,A,3,10,18,31,,,,,,,,,,6.3,3.1,5.4*3E
$BDGSA,A,3,06,07,,,,,,,,,,,6.3,3.1,5.4*24
$GPGSV,3,1,09,10,78,325,24,12,36,064,,14,26,307,,18,67,146,27*71
$GPGSV,3,2,09,21,15,188,,24,13,043,,25,55,119,,31,36,247,30*7F
$GPGSV,3,3,09,32,42,334,*43
$BDGSV,1,1,02,06,68,055,27,07,82,211,31*6A
$GNRMC,084852.000,A,2236.9453,N,11408.4790,E,0.53,292.44,141216,,,A*7
5
$GNVTG,292.44,T,,M,0.53,N,0.98,K,A*2D
$GNZDA,084852.000,14,12,2016,00,00*48
$GPTXT,01,01,01,ANTENNA OK*35
```
2、獲取經緯度及北京時間:
(1)首先使用 uart.read() 函數(shù)從串口讀取一行數(shù)據(jù)。
使用 string.match() 函數(shù)對讀取到的數(shù)據(jù)進行正則匹配,以提取出 "$GNGGA" 行中的經緯度和時間信息。正則表達式為:
?`"%$GNGGA,(%d+%.%d+),(%d+%.%d+),(%a),(%d+%.%d+),(%a),"`?
?其中,括號中的內容表示正則表達式匹配到的結果需要提取出來,具體匹配結果如下:
第一個括號 (%d+%.%d+) 表示匹配一個或多個數(shù)字,可能包含小數(shù)點,表示UTC時間,例如:"084852.000"
第二個括號 (%d+%.%d+) 表示匹配一個或多個數(shù)字,可能包含小數(shù)點,表示緯度,例如:"2236.9453"
第三個括號 (%a) 表示匹配一個字母,表示緯度方向,可能為 "N" 或 "S"
第四個括號 (%d+%.%d+) 表示匹配一個或多個數(shù)字,可能包含小數(shù)點,表示經度,例如:"11408.4790"
第五個括號 (%a) 表示匹配一個字母,表示經度方向,可能為 "E" 或 "W"
(2)使用 tonumber() 函數(shù)將讀取到的經緯度和時間信息從字符串類型轉換為數(shù)字類型,并根據(jù)具體格式進行轉換。例如,對于UTC時間信息,可以使用 string.sub() 函數(shù)獲取小時、分鐘、秒等信息,再進行格式化輸出。
(3)將經緯度轉換為Google Maps格式,即將度分格式轉換為十進制格式,并根據(jù)方向調整正負值。
(4)使用 log.info() 函數(shù)輸出解析后的結果,包括北京時間、緯度和經度等信息。
注:其中,string.match() 函數(shù)的正則表達式 "%$GNGGA,(%d+%.%d+),(%d+%.%d+),(%a),(%d+%.%d+),(%a)," 表示匹配以 "$GNGGA" 開頭的行,并從中提取出符合規(guī)則的內容。具體解釋如下:
(1)%d+%.%d+ 表示匹配一個或多個數(shù)字,可能包含小數(shù)點,例如 "084852.000" 和 "2236.9453"
(2)%a 表示匹配一個字母,例如 "N" 和 "E"
(3)() 表示將括號中的內容作為一個匹配組,需要在 string.match() 函數(shù)的返回值中獲取。
解析出經緯度和時間后,通過數(shù)學運算和字符串格式化等操作,將其轉換為可以直接使用的格式,并使用 log.info() 函數(shù)輸出解析后的結果。