資料介紹
描述
如果你有一只物聯(lián)網(wǎng)寵物,它會吃什么?當(dāng)然是 WiFi SSID!
Nerd 是一種無線電子寵物,通過收集 WiFi SSID 以及一些休息和陽光來生存。為了讓它茁壯成長,你必須平衡離線和在線模式以及明暗,以確保它有一個適當(dāng)?shù)娜粘o嬍?- 睡眠 - 書呆子例程。如果它長時間沒有連接 WiFi,它會使用其內(nèi)置的壓電揚聲器以摩爾斯電碼發(fā)送 SOS。脫機時間越長,蜂鳴聲越多。
簡而言之
Nerd 每半小時醒來一次,掃描它周圍的網(wǎng)絡(luò)。如果它檢測到新網(wǎng)絡(luò),它將存儲它們并以低功耗模式返回睡眠狀態(tài)(以節(jié)省電池壽命)。否則它會通過蜂鳴器發(fā)出噪音來抱怨,直到你喂它或把它放在黑暗中。它還會通過連接到您的 wifi 網(wǎng)絡(luò)了解它何時在家。當(dāng)在家時,書呆子將能夠連接到互聯(lián)網(wǎng)并獲取當(dāng)前時間和日期。如果超過兩天不喂食,它會急劇死亡,發(fā)出很大的聲音。
成分
學(xué)習(xí)目標(biāo)
- 管理完整的 WiFi 功能
- 在閃存中存儲數(shù)據(jù)
- 管理時間和實時時鐘
- 管理低功耗模式
想知道更多?
本教程是讓您熟悉 MKR1010 和物聯(lián)網(wǎng)的一系列實驗的一部分。所有實驗都可以使用 MKR IoT Bundle 中包含的組件來構(gòu)建。
- 帶 MKR WiFi 1010 的我愛你枕頭
- 帶 MKR WiFi 1010 的拼圖盒
- 巴甫洛夫的貓與 MKR WiFi 1010
- 帶 MKR WiFi 1010 的書呆子
- 帶 MKR WiFi 1010 的工廠通訊器
設(shè)置董事會
為了實現(xiàn)所有功能,我們將使用以下庫:
- WiFiNINA //連接到互聯(lián)網(wǎng)并掃描網(wǎng)絡(luò)
- FlashStorage // 保存值,這樣它們就不會在每次重啟時被刪除
- RTCZero // 管理時間觸發(fā)事件
- ArduinoLowPower // 節(jié)省電池電量
- WiFiUdp // 從互聯(lián)網(wǎng)獲取時間和日期
您可以按照本指南中的說明從庫管理器下載它們。
掃描 WiFi 網(wǎng)絡(luò)
書呆子渴望網(wǎng)絡(luò)!掃描網(wǎng)絡(luò)非常簡單, 只需上傳此示例草圖或轉(zhuǎn)到> 示例 > WiFiNINA > ScanNetworksAdvanced以獲得更擴展的版本。
#include
#include
void setup()
{
//Initialize serial and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
} // scan for existing networks:
Serial.println();
Serial.println("Scanning available networks...");
listNetworks();
}
void loop()
{
delay(10000); // scan for existing networks:
Serial.println("Scanning available networks...");
listNetworks();
}
void listNetworks()
{ // scan for nearby networks:
Serial.println("** Scan Networks **");
int numSsid = WiFi.scanNetworks();
if (numSsid == -1)
{
Serial.println("Couldn't get a WiFi connection");
while (true);
} // print the list of networks seen:
Serial.print("number of available networks: ");
Serial.println(numSsid);
// print the network number and name for each network found:
for (int thisNet = 0; thisNet < numSsid; thisNet++) {
Serial.print(thisNet + 1);
Serial.print(" SSID: ");
Serial.println(WiFi.SSID(thisNet));
Serial.flush();
}
Serial.println();
}
在閃存中存儲值
你肯定不希望 Nerd 每次沒電時都死掉!為了避免這種行為,我們將在閃存中保存一些變量(如食物量),以便即使在電路板轉(zhuǎn)動后也可以檢索它們關(guān)閉并再次打開。您可以通過以下方式了解基本功能:
示例 > FlashStorage > FlashStoreAndRetrieve
我們將保存網(wǎng)絡(luò)的名稱,以便 Nerd 只吃一次,我們還將使用保存這些 SSID 的數(shù)組來計算它白天吃的食物量。保存在閃存中的值將保留下來重置電路板但不上傳新草圖。每次上傳新草圖時,閃存也會被清空。此草圖將掃描網(wǎng)絡(luò)并將 SSID 保存在閃存中。
#include
#include
#include
#define MAGIC_NUMBER 0x7423 // arbitrary number to double check the saved SSID
#define MaxNet 30 // max amount of network to be saved
int PosToBeSaved = 0; // Variable used to navigate the array of networks
int daily_amount_of_food = 12; // The amount of food per day needed to survive
// Struct of variable to be saved in flash memory
typedef struct {
int magic;
boolean valid[MaxNet];
char SSIDs[MaxNet][100];
} Networks;
FlashStorage(my_flash_store, Networks);
Networks values;
void setup() {
Serial.begin(115200);
while(!Serial); // wait until the Serial montior has be opened
delay(2000);
values = my_flash_store.read();
if (values.magic == MAGIC_NUMBER) { // If token is correct print saved networks
Serial.println("saved data:");
Serial.println("");
for (int a = 0; a < MaxNet; a++) {
if (values.valid[a]) {
Serial.println(values.SSIDs[a]);
} else {
PosToBeSaved = a;
}
}
}
}
void loop() { // Temporarly save the number of networks
int networks_already_saved = PosToBeSaved;
getNetwork();
if (PosToBeSaved >= daily_amount_of_food) {
Serial.println("Enough food for today");
}
delay(5000);
}
// Feed the Nerd with networks's SSID
void getNetwork() { // scan for nearby networks:
Serial.println("\n*Scan Networks*\n");
int numSsid = WiFi.scanNetworks();
delay(1000);
if (numSsid == -1) {
Serial.println("There are no WiFi networks here..");
} else {
Serial.print("number of available networks: ");
Serial.println(numSsid);
// print the network number and name for each network found:
for (int thisNet = 0; thisNet < numSsid; thisNet++) {
Serial.print("SSID: ");
Serial.println(WiFi.SSID(thisNet));
delay(500);
char* net = WiFi.SSID(thisNet);
bool canBeSaved = true;
// check if the network has already been saved
for (int a = 0; a < PosToBeSaved ; a++) {
if (values.valid[a]) {
if (strncmp(net, values.SSIDs[a], 100) == 0 || strnlen(net, 100) == 0) {
Serial.println("Not saved");
canBeSaved = false;
}
}
}
// Store ssid name
if (canBeSaved && PosToBeSaved < MaxNet) {
if (strlen(net) + 1 < 100 && strlen(net) > 0) {
memset(values.SSIDs[PosToBeSaved], 0, sizeof(values.SSIDs[PosToBeSaved])); // set all characters to zero
memcpy(values.SSIDs[PosToBeSaved], net, strlen(net) + 1); // copy "net" to values.SSDs[thisNet]
values.valid[PosToBeSaved] = true;
values.magic = MAGIC_NUMBER;
my_flash_store.write(values);
Serial.println(String(values.SSIDs[PosToBeSaved]) + " saved in position " + String(PosToBeSaved));
PosToBeSaved ++;
}
else {
Serial.println(" network skipped");
}
}
}
}
}
請注意我們?nèi)绾味x可以保存的最大網(wǎng)絡(luò)數(shù)量,以避免內(nèi)存空間問題:
#define MaxNet 30
int PosToBeSaved = 0;
已用于導(dǎo)航保存網(wǎng)絡(luò)名稱的數(shù)組并測量已經(jīng)吃掉的食物量。
管理時間
我們可以將實時時鐘 (RTC) 的功能與 WiFi 相結(jié)合,以獲取當(dāng)前時間和日期,然后設(shè)置電路板的內(nèi)部時鐘。通過這種方式,我們可以在很長一段時間內(nèi)觸發(fā)基于時間的事件,而無需使用millis()
將毫秒轉(zhuǎn)換為天時可能會很棘手的功能。我們將從網(wǎng)絡(luò)時間協(xié)議(NTP) 時間服務(wù)器獲取時間,然后設(shè)置 RTC用它。請注意,收到的時間采用紀(jì)元格式,即自 1970 年 1 月 1 日以來的秒數(shù)。您可以從示例 > WiFiNINA> WiFiUdpNtpClient運行基本草圖在下面的草圖中,我們將所有內(nèi)容放在一起:掃描網(wǎng)絡(luò)功能和時間相關(guān)的。
-
bool atHome = false;
用于觸發(fā) WiFi 連接,因此請求服務(wù)器獲取時間。 -
check_home()
用于掃描所有可用網(wǎng)絡(luò),并查看其中一個是否是家庭 WiFi 網(wǎng)絡(luò)。 -
connect_WiFi()
然后調(diào)用,它會將開發(fā)板連接到 WiFi,觸發(fā)對服務(wù)器的請求并打印當(dāng)前時間。 -
rtc.setEpoch(epoch + GMT);
用于以紀(jì)元格式的當(dāng)前時間啟動 RTC,修改 GMT 變量以將時間調(diào)整為您當(dāng)前的時區(qū)。
#include
#include
#include
#define MAGIC_NUMBER 0x7423 // arbitrary number to double check the saved SSID
#define MaxNet 30 // max amount of network to be saved
int PosToBeSaved = 0; // Variable used to navigate the array of networks
int daily_amount_of_food = 12; // The amount of food per day needed to survive
// Struct of variable to be saved in flash memory
typedef struct {
int magic;
boolean valid[MaxNet];
char SSIDs[MaxNet][100];
} Networks;
FlashStorage(my_flash_store, Networks);
Networks values;
void setup() {
Serial.begin(115200);
while(!Serial); // wait until the Serial montior has be opened
delay(2000);
values = my_flash_store.read(); // Read values from flash memory
if (values.magic == MAGIC_NUMBER) {
Serial.println("saved data:");
Serial.println("");
for (int a = 0; a < MaxNet; a++) {
if (values.valid[a]) {
Serial.println(values.SSIDs[a]);
} else {
PosToBeSaved = a;
}
}
}
}
void loop() { // Temporarly save the number of networks
int networks_already_saved = PosToBeSaved;
getNetwork();
if (PosToBeSaved >= daily_amount_of_food) {
Serial.println("Enough food for today");
}
delay(5000);
}
// Feed the Nerd with networks's SSID
void getNetwork() { // scan for nearby networks:
Serial.println("\n*Scan Networks*\n");
int numSsid = WiFi.scanNetworks();
delay(1000);
if (numSsid == -1) {
Serial.println("There are no WiFi networks here..");
} else {
Serial.print("number of available networks: ");
Serial.println(numSsid);
// print the network number and name for each network found:
for (int thisNet = 0; thisNet < numSsid; thisNet++) {
Serial.print("SSID: ");
Serial.println(WiFi.SSID(thisNet));
delay(500);
char* net = WiFi.SSID(thisNet);
bool canBeSaved = true;
// check if the network has already been saved
for (int a = 0; a < PosToBeSaved ; a++) {
if (values.valid[a]) {
if (strncmp(net, values.SSIDs[a], 100) == 0 || strnlen(net, 100) == 0) {
Serial.println("Not saved");
canBeSaved = false;
}
}
}
// Store ssid name
if (canBeSaved && PosToBeSaved < MaxNet) {
if (strlen(net) + 1 < 100 && strlen(net) > 0) {
memset(values.SSIDs[PosToBeSaved], 0, sizeof(values.SSIDs[PosToBeSaved]));
memcpy(values.SSIDs[PosToBeSaved], net, strlen(net) + 1);
values.valid[PosToBeSaved] = true;
values.magic = MAGIC_NUMBER;
my_flash_store.write(values);
Serial.println(String(values.SSIDs[PosToBeSaved]) + " saved in position " + String(PosToBeSaved));
PosToBeSaved ++;
}
else {
Serial.println(" network skipped");
}
}
}
}
}
實現(xiàn)當(dāng)前時間允許我們使用像這樣的簡單函數(shù)來管理 Nerd 的生死:
if(rtc.getEpoch() - values.last_time_fed >= 86400*2){
// complain and eventually die :(
}
其中86400
是一天中的秒數(shù), 是書呆子最后一次被喂食的紀(jì)元格式values.last_time_fed
時間的存儲值,并以紀(jì)元格式返回當(dāng)前時間。rtc.getEpoch()
低功耗模式
我們可以使用低功耗模式讓我們的電路板進(jìn)入睡眠狀態(tài)。這意味著它將禁用大部分功能(包括 WiFi)以節(jié)省電池電量。由于我們希望書呆子定期醒來,我們可以輕松設(shè)置一個計時器:
#include "ArduinoLowPower.h"
int sleeping_time = 5000; // 5 seconds
bool awake = true;
void setup() {
Serial.begin(9600);
LowPower.attachInterruptWakeup(RTC_ALARM_WAKEUP, WakeUp, CHANGE);
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
if (awake) {
digitalWrite(LED_BUILTIN, HIGH);
delay(500);
digitalWrite(LED_BUILTIN, LOW);
delay(500);
}
awake = false;
Serial.println("going to sleep");
LowPower.sleep(sleeping_time);
}
void WakeUp() {
Serial.println("awake");
awake = true;
}
請注意,該WakeUp()
函數(shù)附加到中斷,這意味著它不能包含任何包含延遲的代碼。但是我們可以設(shè)置 s 布爾變量 so 來觸發(fā)循環(huán)中的事件。
- MKR WiFi 1010 + MKR RS 485 Shield連接到Ignition
- 使用Arduino MKR1000通過WiFi進(jìn)行HID攻擊
- 帶Arduino IoT捆綁包的書呆子
- 使用Arduino Mkr Wifi 1010和Thincloud構(gòu)建連接燈的過程
- 帶有Arduino MKR1010和MKR RGB Shield的Otto Biped
- 將MQTT協(xié)議物聯(lián)網(wǎng)與Arduino MKR1010 WiFi結(jié)合使用
- 我愛你枕頭與MKR WiFi 1010開源分享
- 帶有MKR WiFi 1010的植物通訊器
- 使用Grove Sensor的Arduino MKR1010和阿里云IoT
- GBU1010-ASEMI規(guī)格書英文版下載 0次下載
- KBJ10005-THRU-KBJ1010規(guī)格書 4次下載
- 基于ITM-MKR680Temperature Sensing的參考設(shè)計1
- 基于ITM-MKR680Temperature Sensing的參考設(shè)計
- 數(shù)據(jù)處理有9大編程語言詳細(xì)資料介紹 3次下載
- RFLA1010低噪聲放大器的詳細(xì)數(shù)據(jù)手冊免費下載
- 如何制造世界上最小的三電子管收音機 1428次閱讀
- 寬禁帶器件和仿真環(huán)境介紹 1457次閱讀
- 什么是wifi6,與wifi2.4g和wifi5g有什么區(qū)別 5.4w次閱讀
- MKR Vidor 4000一款拇指型的FPGA開發(fā)板 1174次閱讀
- 什么是2.4G WIFI 什么是5G WiFi 3.6w次閱讀
- 簡評FPGA——Arduino MKR Vidor 4000 6807次閱讀
- 細(xì)說WiFi信號與路由器和WiFi模塊的關(guān)系 1.2w次閱讀
- 了解機器學(xué)習(xí)算法的類別,把握對問題的認(rèn)識層次 697次閱讀
- wifi探針技術(shù)的應(yīng)用領(lǐng)域_公安局wifi探針用途 2.3w次閱讀
- wifi探針是什么_wifi探針的工作原理詳解 4.6w次閱讀
- wifi模塊異常是怎么回事_wifi模塊異常怎樣解決 6.9w次閱讀
- 手機wifi模塊在哪里_手機wifi模塊位置圖解 13.9w次閱讀
- 自制WiFi中繼器方法詳解 3.7w次閱讀
- 雙頻wifi是什么意思_雙頻wifi的優(yōu)點 2.7w次閱讀
- WiFi信號是怎樣傳播的? 1.2w次閱讀
下載排行
本周
- 1山景DSP芯片AP8248A2數(shù)據(jù)手冊
- 1.06 MB | 532次下載 | 免費
- 2RK3399完整板原理圖(支持平板,盒子VR)
- 3.28 MB | 339次下載 | 免費
- 3TC358743XBG評估板參考手冊
- 1.36 MB | 330次下載 | 免費
- 4DFM軟件使用教程
- 0.84 MB | 295次下載 | 免費
- 5元宇宙深度解析—未來的未來-風(fēng)口還是泡沫
- 6.40 MB | 227次下載 | 免費
- 6迪文DGUS開發(fā)指南
- 31.67 MB | 194次下載 | 免費
- 7元宇宙底層硬件系列報告
- 13.42 MB | 182次下載 | 免費
- 8FP5207XR-G1中文應(yīng)用手冊
- 1.09 MB | 178次下載 | 免費
本月
- 1OrCAD10.5下載OrCAD10.5中文版軟件
- 0.00 MB | 234315次下載 | 免費
- 2555集成電路應(yīng)用800例(新編版)
- 0.00 MB | 33566次下載 | 免費
- 3接口電路圖大全
- 未知 | 30323次下載 | 免費
- 4開關(guān)電源設(shè)計實例指南
- 未知 | 21549次下載 | 免費
- 5電氣工程師手冊免費下載(新編第二版pdf電子書)
- 0.00 MB | 15349次下載 | 免費
- 6數(shù)字電路基礎(chǔ)pdf(下載)
- 未知 | 13750次下載 | 免費
- 7電子制作實例集錦 下載
- 未知 | 8113次下載 | 免費
- 8《LED驅(qū)動電路設(shè)計》 溫德爾著
- 0.00 MB | 6656次下載 | 免費
總榜
- 1matlab軟件下載入口
- 未知 | 935054次下載 | 免費
- 2protel99se軟件下載(可英文版轉(zhuǎn)中文版)
- 78.1 MB | 537798次下載 | 免費
- 3MATLAB 7.1 下載 (含軟件介紹)
- 未知 | 420027次下載 | 免費
- 4OrCAD10.5下載OrCAD10.5中文版軟件
- 0.00 MB | 234315次下載 | 免費
- 5Altium DXP2002下載入口
- 未知 | 233046次下載 | 免費
- 6電路仿真軟件multisim 10.0免費下載
- 340992 | 191187次下載 | 免費
- 7十天學(xué)會AVR單片機與C語言視頻教程 下載
- 158M | 183279次下載 | 免費
- 8proe5.0野火版下載(中文版免費下載)
- 未知 | 138040次下載 | 免費
評論
查看更多