我做了一個(gè) GPS 追蹤器來追蹤我孩子上學(xué)后的位置,并且能夠讓他們隨時(shí)發(fā)送接送請求,以此能讓我做好去接他們放學(xué)的準(zhǔn)備。
背景
我的雙胞胎喜歡騎自行車在小徑上騎行,而且他們已經(jīng)到了可以騎得比我快得多的年齡。作為父母,我想鼓勵(lì)他們自己探索,但我也想密切關(guān)注他們的位置,以防出現(xiàn)問題。
我的孩子們對于手機(jī)的認(rèn)知還不夠,所以我試圖盡可能避免再重復(fù)兩個(gè)數(shù)據(jù)計(jì)劃。雖然說市面上已經(jīng)有很多商業(yè)兒童 GPS 追蹤器可用,但幾乎所有追蹤器都需要支付一筆額外的每月訂閱費(fèi)。
以上的這一切讓我開始思考——作為一名軟件開發(fā)人員,我應(yīng)該能夠?yàn)樽约簶?gòu)建這樣的東西。
所以誕生了這個(gè)項(xiàng)目!
我的自定義跟蹤器每五分鐘讀取一次 GPS 讀數(shù)并將其顯示在地圖上。此外,跟蹤器包括一個(gè)按鈕,孩子們可以按下該按鈕通過短信將他們的位置發(fā)送給父母。
在本文中,我將向您展示我如何構(gòu)建自己的自定義 GPS 跟蹤器,并教您如何自己復(fù)制此設(shè)置的部分,讓我們開始吧。
第 1 步:組裝硬件
我使用的大部分硬件都來自Swan 的 Blues Wireless Feather Starter Kit。Feather Starter 套件包含一個(gè) Notecard、一個(gè) Notecarrier AF 和一個(gè) Swan MCU。讓我們分解它們中的每一個(gè)。
Notecard
Notecard是一個(gè)小型系統(tǒng)級模塊,可以為幾乎任何物聯(lián)網(wǎng)項(xiàng)目添加連接性。Blues 生產(chǎn)蜂窩和 Wi-Fi 記事卡,但對于 GPS 跟蹤,您需要使用蜂窩記事卡。
我使用 Notecard 從外部天線(我將立即展示)收集 GPS 坐標(biāo),并通過蜂窩連接將這些坐標(biāo)發(fā)送到云端。
NoteAF
Notecarriers 是配套板,可以輕松地使用 Notecard 進(jìn)行物聯(lián)網(wǎng)項(xiàng)目的原型設(shè)計(jì)和部署。Notecarrier 為您提供了一個(gè)方便的地方來連接 Notecard、為其供電、訪問嵌入式天線以及通過 Qwiic 端口連接到 I2C 外圍設(shè)備。
Notecarrier AF 還包含與 Feather 兼容的接頭,可以輕松嵌入任何與 Feather 兼容的設(shè)備以與 Notecard 一起使用。
Swan
Notecarrier 可以輕松連接與 Feather 兼容的 MCU,而我使用的 MCU 是Swan。Swan 幾乎可以驅(qū)動(dòng)任何物聯(lián)網(wǎng)項(xiàng)目,因?yàn)樗鼡碛?640KB 的大容量 RAM,可擴(kuò)展至 55 個(gè)引腳以訪問額外的 I/O 和總線,并內(nèi)置對 C/C++、Arduino 和 CircuitPython 的支持。
組裝
要組裝此版本,您需要將 Notecard 和 Swan 都插入 Notecarrier AF。Blues 有一個(gè)很好的圖片指南,如果您是第一次設(shè)置,我建議您遵循這些圖片。
組裝好零件后,您將擁有一個(gè)看起來像這樣的設(shè)置。
為了完成構(gòu)建,我確實(shí)添加了最后兩件事。首先,我在 Notecarrier AF的插座上添加了一個(gè)外部Molex 天線。雖然 Notecarrier AF 有一個(gè)內(nèi)置天線,但外部天線能夠更快地接收 GPS 信號(hào),這對我來說對這個(gè)項(xiàng)目很重要。
接下來,我添加了一個(gè)小型 Lipo 電池,并將其BATTERY連接到 Notecarrier AF 上的 JST 連接器。當(dāng)我在辦公室外使用時(shí),鋰電池為設(shè)備供電。
這是安裝天線和電池后的設(shè)置:
注意:Notecarrier-AF 包括一個(gè)微型 USB 端口,如果您為該端口供電,您可以為連接的鋰電池充電。
最后,因?yàn)槲也幌M⒆觽兪褂盟鼤r(shí)一堆松散的碎片四處飛揚(yáng),所以我將鋰電池用膠帶粘在 Notecarrier AF 的背面,并將 Molex 天線的粘性面也貼在背面(中間有一點(diǎn)紙板)。
從長遠(yuǎn)來看,我想為該設(shè)備建造一個(gè)漂亮的外殼,但對于原型設(shè)計(jì),這給了我一件我的孩子可以隨身攜帶的物品。
現(xiàn)在您已經(jīng)看到了硬件的樣子,接下來讓我們看看如何設(shè)置云后端。
第 2 步:設(shè)置云后端
Notecard 的一大優(yōu)點(diǎn)是它知道如何將數(shù)據(jù)發(fā)送到云后端Notehub,開箱即用。Notehub 是一種托管服務(wù),旨在連接到 Notecard 設(shè)備并同步數(shù)據(jù)。
如果您跟隨并想自己構(gòu)建這個(gè)項(xiàng)目,您需要在notehub.io 上設(shè)置一個(gè)帳戶,然后創(chuàng)建一個(gè)新項(xiàng)目。
創(chuàng)建項(xiàng)目后,請確保復(fù)制新項(xiàng)目的 ProductUID(參見下面的屏幕截圖),因?yàn)槟枰摌?biāo)識(shí)符才能將 Notecard 連接到新的 Notehub 項(xiàng)目。
第 3 步:編寫代碼
如果您還記得第 1 步,我正在使用 Swan MCU 來執(zhí)行驅(qū)動(dòng)兒童跟蹤器的代碼。Swan 支持 CircuitPython 和 Arduino,因此您可以使用其中任何一個(gè),但我選擇了 Arduino,因?yàn)樗俏抑霸?Swan 上多次使用過的平臺(tái)。
如果您是 Swan 新手,您需要先閱讀Swan 快速入門,這將幫助您設(shè)置開發(fā)環(huán)境。如果您想使用與我相同的環(huán)境,請完成使用 Arduino IDE部分。
設(shè)置好開發(fā)環(huán)境后,您就可以繼續(xù)編寫代碼本身了。在代碼中,您需要處理三件主要的事情:
配置記事卡
配置獲取 GPS 讀數(shù)的頻率
處理按鈕按下
讓我們依次解決這些問題。
注意:該項(xiàng)目的完整源代碼可在下方找到。
配置Notecard
我們的第一個(gè)編碼任務(wù)是設(shè)置Notecard。Notecard 的 API 是基于 JSON 的,因此配置 Notecard 就像發(fā)送幾個(gè) JSON 請求一樣簡單。
您可以通過在線游樂場、CLI或Arduino、Python、C/C++ 或 Go 的 SDK發(fā)送這些請求。在這種情況下,我們在 Swan MCU 上運(yùn)行,因此我們將使用note-arduino,這是通過 Arduino 兼容的微控制器與 Notecard 進(jìn)行通信的官方庫。
具體來說,您需要確保使用項(xiàng)目的安裝說明在 Arduino IDE 中安裝庫。note-arduino
之后,您需要從 Arduino 草圖中的以下代碼開始:
#include
#define serialDebug Serial
#define productUID "com.blues.tj:kidtracker"
Notecard notecard;
void setup() {
serialDebug.begin(115200);
notecard.begin();
notecard.setDebugOutputStream(serialDebug);
J *req1 = notecard.newRequest("hub.set");
JAddStringToObject(req1, "product", productUID);
JAddStringToObject(req1, "mode", "periodic");
JAddNumberToObject(req1, "outbound", 5);
notecard.sendRequest(req1);
serialDebug.println("Setup complete");
}
注意:如果您繼續(xù)進(jìn)行操作,請確保將“com.blues.tj:kidtracker”更改為您在上一步中復(fù)制的 ProductUID。
首先,它初始化 Notecard ( notecard.begin()) 并設(shè)置調(diào)試輸出流 ( notecard.setDebugOutputStream(serialDebug)),這允許您使用 Arduino IDE 的串行監(jiān)視器查看日志。
接下來,代碼使用 note-arduino 庫格式化新hub.set命令并將其發(fā)送到 Notecard
J *req1 = notecard.newRequest("hub.set");
JAddStringToObject(req1, "product", productUID);
JAddStringToObject(req1, "mode", "periodic");
JAddNumberToObject(req1, "outbound", 5);
notecard.sendRequest(req1);
該hub.set命令控制您要將數(shù)據(jù)發(fā)送到哪個(gè) Notehub 項(xiàng)目,并允許您為 Notecard 的工作方式設(shè)置一些基本配置。
設(shè)置"mode"為"periodic"告訴記事本定期連接到蜂窩網(wǎng)絡(luò),設(shè)置"outbound"為5告訴記事本每五分鐘嘗試一次連接。Notecard 也可以在連續(xù)模式下工作 ( "mode": "continuous"),但保持蜂窩調(diào)制解調(diào)器連接的恒定會(huì)消耗大量電池。
每五分鐘發(fā)送一次數(shù)據(jù)已經(jīng)相當(dāng)耗電,但對于這個(gè)項(xiàng)目,我希望在孩子們騎自行車時(shí)經(jīng)??吹綌?shù)據(jù),而且在兩次使用之間為設(shè)備的鋰電池充電也沒有問題。如果您的項(xiàng)目需要在電池使用方面更加保守,您需要將該"outbound"值設(shè)置為相當(dāng)高的數(shù)字。
此時(shí)您可以將您的程序發(fā)送給 Swan進(jìn)行測試。如果一切順利,您應(yīng)該在 Arduino 串行監(jiān)視器中看到以下內(nèi)容:
注意:如果您沒有看到日志,您可以在while (!serialDebug)之后添加serialDebug.begin(),這會(huì)強(qiáng)制程序等到調(diào)試器可用后再繼續(xù)。只需確保while (!serialDebug)在準(zhǔn)備好部署設(shè)備時(shí)記得刪除,因?yàn)槿绻诓淮嬖诖姓{(diào)試器的情況下運(yùn)行,它將導(dǎo)致無限循環(huán)。
如果您返回到您的 Notehub 項(xiàng)目,您現(xiàn)在應(yīng)該會(huì)看到您的設(shè)備已列出:
此時(shí),您的 Notecard 已連接到 Notehub,這意味著您已準(zhǔn)備好發(fā)送位置數(shù)據(jù)。接下來讓我們看看如何配置 Notecard 以收集該位置信息。
配置獲取 GPS 讀數(shù)的頻率
Notecard 有許多請求,可讓您準(zhǔn)確配置應(yīng)如何獲取 GPS 讀數(shù)。您需要向記事卡發(fā)送兩個(gè)主要命令:card.location.mode和card.location.track.
下面的代碼(您可以在現(xiàn)有hub.set代碼下添加)發(fā)出這兩個(gè)請求。
J *req2 = notecard.newRequest("card.location.mode");
JAddStringToObject(req2, "mode", "periodic");
JAddNumberToObject(req2, "seconds", 300);
notecard.sendRequest(req2);
J *req3 = notecard.newRequest("card.location.track");
JAddBoolToObject(req3, "start", true);
JAddBoolToObject(req3, "heartbeat", true);
JAddNumberToObject(req3, "hours", 12);
notecard.sendRequest(req3);
在card.location.mode通話中,設(shè)置"mode"to"periodic"告訴 Notecard 定期激活其 GPS 模塊(而不是連續(xù)),設(shè)置"seconds"to300告訴 Notecard 嘗試每 300 秒或五分鐘讀取一次 GPS 讀數(shù)。
該card.location.track請求啟動(dòng)實(shí)際的跟蹤過程。在周期性 GPS 模式下,Notecard 足夠智能,僅在設(shè)備移動(dòng)時(shí)才獲取 GPS 讀數(shù)(它使用內(nèi)置的加速度計(jì)知道這一點(diǎn))。將heartbeat選項(xiàng)設(shè)置為true告訴記事卡每 12 小時(shí)讀取一次(因?yàn)槲覀冊O(shè)置"hours"為12),即使記事卡沒有移動(dòng)。
簡而言之,這些請求告訴 Notecard 開始獲取 GPS 讀數(shù);如果設(shè)備正在移動(dòng),則每五分鐘讀取一次;如果沒有,則每十二小時(shí)閱讀一次。
注意:如果您想了解有關(guān)如何將 Notecard 配置為資產(chǎn)跟蹤器的更多信息,請務(wù)必閱讀Notecard 的資產(chǎn)跟蹤綜合指南。
如果您將此程序發(fā)送到您的 Swan,您應(yīng)該會(huì)在串行監(jiān)視器中看到以下輸出:
更重要的是,如果您查看 Notehub 項(xiàng)目中的“事件”選項(xiàng)卡,您應(yīng)該會(huì)開始看到_track.qo進(jìn)入的文件。
如果您雙擊一個(gè)事件并轉(zhuǎn)到下一頁的 JSON 選項(xiàng)卡,您可以查看捕獲的 GPS 信息。
可能需要幾分鐘才能看到您的第一個(gè)事件,因?yàn)橛浭驴赡苄枰恍r(shí)間才能建立 GPS 連接。盡量將您的設(shè)備放置在對天空有清晰視線的位置,并盡可能避開地下室等狹窄地方。
此外,請記住,Notecard 僅在設(shè)備移動(dòng)時(shí)才會(huì)獲取新的 GPS 讀數(shù),因此您可能需要稍微搖晃設(shè)備才能_track.qo在測試期間看到后續(xù)文件進(jìn)入。
稍后我們將看看如何在地圖上可視化您的 GPS 讀數(shù),但讓我們首先結(jié)束這個(gè)項(xiàng)目的代碼,看看如何讓按下按鈕發(fā)送帶有位置的 SMS 消息。
通知按鈕
我希望我的追蹤器有一個(gè)孩子可以按下的按鈕,并讓該按鈕向父母發(fā)送一條帶有追蹤器當(dāng)前位置的短信。這是大多數(shù)商業(yè)兒童追蹤器的一個(gè)功能,所以我相信這也是其他父母想要的。
有很多方法可以處理 IoT 應(yīng)用程序中的按鈕按下,但 Swan 包含一個(gè)用戶按鈕 ( USER_BTN),用于處理這種確切的場景。
要使用此按鈕,您可以#define先在草圖頂部添加以下行。
#define BUTTON_PIN USER_BTN
接下來,添加以下布爾值,您將使用它來跟蹤用戶是否請求了他們的位置。
bool locationRequested = false;
之后,將以下代碼添加到現(xiàn)有setup()函數(shù)的末尾。此代碼將中斷附加到您的 Swan 按鈕,并在觸發(fā)時(shí)調(diào)用名為ISR.
pinMode(BUTTON_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), ISR, FALLING);
您需要定義ISR(中斷服務(wù)例程),您可以通過將以下函數(shù)添加到您的草圖來完成。
void ISR(void) {
serialDebug.println("Button pressed");
locationRequested = true;
}
locationRequested當(dāng)用戶按下 Swan 的用戶按鈕時(shí),您的程序現(xiàn)在會(huì)更改布爾值。要響應(yīng)該更改,您需要在 Arduinoloop()函數(shù)中監(jiān)視該布爾值。您可以使用下面的代碼來做到這一點(diǎn)。
void loop() {
if (!locationRequested) {
return;
}
J *req = notecard.newRequest("card.location");
J *resp = notecard.requestAndResponse(req);
serialDebug.println("Location:");
double lat = JGetNumber(resp, "lat");
double lon = JGetNumber(resp, "lon");
serialDebug.println(lat, 10);
serialDebug.println(lon, 10);
if (lat == 0) {
serialDebug.println("The Notecard does not yet have a location");
// Wait a minute before trying again.
delay(1000 * 60);
return;
}
// http://maps.google.com/maps?q=,
char buffer[100];
snprintf(
buffer,
sizeof(buffer),
"Your kids are requesting you. https://maps.google.com/maps?q=%.8lf,%.8lf",
lat,
lon
);
serialDebug.println(buffer);
J *req2 = notecard.newRequest("note.add");
JAddStringToObject(req2, "file", "twilio.qo");
JAddBoolToObject(req2, "sync", true);
J *body = JCreateObject();
JAddStringToObject(body, "message", buffer);
JAddItemToObject(req2, "body", body);
notecard.sendRequest(req2);
locationRequested = false;
serialDebug.println("Location sent successfully.");
}
這里有很多,所以讓我們分解這段代碼。首先,請注意這里的所有邏輯都由if (!locationRequested) { return; }檢查門控。也就是,如果用戶沒有按下按鈕,在loop().
如果用戶請求了一個(gè)位置,我們接下來使用 Notecard 的card.location請求來獲取當(dāng)前位置并將其打印出來。
J *req = notecard.newRequest("card.location");
J *resp = notecard.requestAndResponse(req);
serialDebug.println("Location:");
double lat = JGetNumber(resp, "lat");
double lon = JGetNumber(resp, "lon");
serialDebug.println(lat, 10);
serialDebug.println(lon, 10);
Notecard 可能還沒有位置(項(xiàng)目啟動(dòng)時(shí)需要幾分鐘才能獲取 GPS 位置),因此我們接下來檢查是否card.location返回了有效位置。如果沒有,我們會(huì)記錄另一條消息,并等待一分鐘后再重試。
if (lat == 0) {
serialDebug.println("The Notecard does not yet have a location");
// Wait a minute before trying again.
delay(1000 * 60);
return;
}
如果我們確實(shí)有一個(gè)有效的位置,我們接下來會(huì)格式化一條消息,其中包含指向跟蹤器當(dāng)前位置的 Google 地圖鏈接。
char buffer[100];
snprintf(
buffer,
sizeof(buffer),
"Your kids are requesting you. https://maps.google.com/maps?q=%.8lf,%.8lf",
lat,
lon
);
serialDebug.println(buffer);
之后,我們使用 Notecard 的note.add請求將消息發(fā)送到 Notehub。
J *req2 = notecard.newRequest("note.add");
JAddStringToObject(req2, "file", "twilio.qo");
JAddBoolToObject(req2, "sync", true);
J *body = JCreateObject();
JAddStringToObject(body, "message", buffer);
JAddItemToObject(req2, "body", body);
notecard.sendRequest(req2);
最后,我們將布爾值翻轉(zhuǎn)回false,因?yàn)槲覀儸F(xiàn)在已經(jīng)完成了按鈕按下的處理。
locationRequested = false;
serialDebug.println("Location sent successfully.");
這樣,您就完成了編寫運(yùn)行該項(xiàng)目所需的代碼!在最后一次將代碼推送到設(shè)備之前,進(jìn)入 Arduino IDE 的工具菜單,并將C 運(yùn)行時(shí)庫切換到支持浮點(diǎn)打印和掃描的庫,因?yàn)槲覀冊诜胖镁暥群徒?jīng)度的邏輯中使用它進(jìn)入谷歌地圖網(wǎng)址。
-
gps
+關(guān)注
關(guān)注
22文章
2896瀏覽量
166270 -
跟蹤器
+關(guān)注
關(guān)注
0文章
131瀏覽量
20040
發(fā)布評論請先 登錄
相關(guān)推薦
評論