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