加入星計劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長期合作伙伴
立即加入
  • 正文
    • 氣象站項(xiàng)目預(yù)覽
    • ESP-NOW概述
    • ESP-NOW的優(yōu)勢
    • ESP-NOW通信
    • 硬件
    • 軟件
  • 推薦器件
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請入駐 產(chǎn)業(yè)圖譜

老宇哥帶你玩轉(zhuǎn) ESP32:14 親自動手做一個雙向通訊的無線遙控器(一)

09/21 15:44
5.3萬
閱讀需 19 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

今天我們來玩兒ESP-NOW。

相信每個玩電子的童鞋對無線通信都非常感興趣,從孩童時期的無線遙控賽車,到學(xué)生時期的收音機(jī),到長大后接觸的各種無線控制的家電,手機(jī)等電子產(chǎn)品,無線通信讓我們可以像神話小說中的某些絕技,可以做到隔空控制,每個人都都希望將那個遙控器掌握在自己手中。

無線遙控的本質(zhì)就是發(fā)射端發(fā)射某個頻率的電磁波出去,接收端接收并解碼這個信號。我們經(jīng)常接觸的空調(diào),電視,風(fēng)扇等遙控器很多都是紅外的,頻率大多是38Khz;窗簾,車庫門等大多是315MHz或者433MHz;國外有868MHz、915MHz等;低于1Ghz的泛稱為Sub 1Ghz,不同國家有不同的免費(fèi)頻率段;燈,手機(jī)等大多是用2.4Ghz的,2.4G這個頻段用的比較多,這個頻段在全球是免費(fèi)使用的,我們熟知的WiFi、藍(lán)牙、Zigbee的都是2.4Ghz的;當(dāng)然還有NBIOT,2G,4G,5G,長波,中波,短波等很多頻率的設(shè)備。理論來說,在相同功率下,低頻能獲得更好的傳送距離,高頻有更好的抗干擾性能,不同領(lǐng)域根據(jù)自身特性選擇最合適的通信頻率。

氣象站項(xiàng)目預(yù)覽

ESP-NOW概述

ESP-NOW 是由 Espressif 開發(fā)的一種協(xié)議,它使多個設(shè)備能夠在不使用 Wi-Fi 的情況下相互通信。該協(xié)議類似于無線鼠標(biāo)中用的2.4GHz無線連接。因此,設(shè)備之間的配對需要在它們通信之前進(jìn)行。配對完成后,連接是安全且點(diǎn)對點(diǎn)的,無需握手,也就是他不像TCP/IP等是長連接的,換句話說,它是無連接的,如果其中一個板子突然斷電,重新啟動后,會自動匹配它的連接設(shè)備繼續(xù)通信。

不同于傳統(tǒng)的OSI模型,ESP-NOW去掉了其中一些層,只保留最基本的傳輸層,減少了網(wǎng)絡(luò)擁堵造成的丟包延遲,實(shí)現(xiàn)快速響應(yīng)。簡單來說,ESP-NOW 是一種快速通信協(xié)議,可用于在 ESP32 板之間交換短消息(單次最多 250 字節(jié))。

ESP-NOW的優(yōu)勢

  • 快速響應(yīng):開機(jī)后,設(shè)備無需任何無線連接即可直接傳輸數(shù)據(jù)和控制其他配對設(shè)備,響應(yīng)速度以毫秒為單位;
  • 遠(yuǎn)距離通信:ESP-NOW 支持遠(yuǎn)距離通信,板載天線戶外空曠距離能達(dá)到200米+;
  • 多跳控制:ESP-NOW可以實(shí)現(xiàn)設(shè)備的多跳控制,可通過單播、廣播和群控方式控制數(shù)百臺設(shè)備;
  • 新配網(wǎng)方式:提供了除 Wi-Fi 和藍(lán)牙之外的新方式,通過藍(lán)牙為第一臺設(shè)備配置網(wǎng)絡(luò),其他設(shè)備不需要配置SSID/密碼等信息,第一臺連接到網(wǎng)絡(luò)的設(shè)備可以直接將這些信息發(fā)送給其他設(shè)備;
  • 升級:可用于固件升級或者大量數(shù)據(jù)升級的場景;
  • 調(diào)試:在一些高溫高壓等不太方便的場合,可以接收多個設(shè)備的數(shù)據(jù),快速診斷設(shè)備故障。
  • 低成本:可與WiFi,藍(lán)牙等共存;
  • 安全:ESP-NOW 采用 CCMP 方法保護(hù)供應(yīng)商特定動作幀的安全,具體可參考 IEEE Std. 802.11-2012。

ESP-NOW通信

單向通信

一個從機(jī)向一個主機(jī)發(fā)送數(shù)據(jù)

這種情況適用于一個設(shè)備向另一個設(shè)備單向發(fā)送數(shù)據(jù),比如一個從機(jī)采集傳感器數(shù)據(jù)或?qū)?a class="article-link" target="_blank" href="/tag/%E5%BC%80%E5%85%B3/">開關(guān)量發(fā)送到主機(jī)。

一個主機(jī)向多個從機(jī)發(fā)送數(shù)據(jù)

一個從機(jī)從多個主機(jī)接收數(shù)據(jù)

雙向通信

主機(jī)與從機(jī)互相通信

多個設(shè)備之間互相通信

ESP-NOW非常適合組建一個小型網(wǎng)絡(luò),可以讓多個ESP32之間交換數(shù)據(jù)。

硬件

基本演示不需要加入其它外設(shè),板子接上串口助手觀察就好了。

軟件

獲取板子的MAC地址

ESP-NOW是通過MAC地址做為不同設(shè)備的唯一識別的,就像不同設(shè)備的ID碼一樣,當(dāng)然我們可以通過掃描配對的方式去自動配對,這里為了方便展示程序原理,我們就先采用最基本的方式,先通過下面的代碼獲取主機(jī)設(shè)備的MAC地址。

#include?"WiFi.h"
?
void?setup(){
??Serial.begin(115200);
??WiFi.mode(WIFI_MODE_STA);
??Serial.println(WiFi.macAddress());
}
?
void?loop(){

}

獲取到主機(jī)的MAC地址后,我們記下來。

初始化ESP-NOW

初始化ESP-NOW,在這個函數(shù)調(diào)用之前必須初始化WiFi。

esp_now_init();

添加配對設(shè)備

調(diào)用此函數(shù)配對設(shè)備,將MAC地址,通道,加密信息等進(jìn)行配置。

esp_now_add_peer();

發(fā)送數(shù)據(jù)

向配對設(shè)備發(fā)送數(shù)據(jù)

esp_now_send();

發(fā)送數(shù)據(jù)回調(diào)函數(shù)

注冊一個發(fā)送數(shù)據(jù)時調(diào)用的函數(shù),此函數(shù)會返回是否發(fā)送成功的消息。

esp_now_register_send_cb();

接收數(shù)據(jù)回調(diào)函數(shù)

注冊一個接收到數(shù)據(jù)時調(diào)用的函數(shù)。

esp_now_register_rcv_cb();

還有其它一些函數(shù),我們用到的時候再講。

完整發(fā)送程序

我們將之前打印的MAC地址保存下來,替換到broadcastAddress數(shù)組中。代碼中,首先定義了一個結(jié)構(gòu)體,包含幾種不同類型的數(shù)據(jù)變量,這個就是我們要發(fā)送的數(shù)據(jù),在setup()中先設(shè)置WiFi工作在STA模式,然后調(diào)用esp_now_init()初始化,將配對設(shè)備的信息進(jìn)行添加,簡單配置一下發(fā)送回調(diào)函數(shù),打印是否發(fā)送成功,主函數(shù)中,每2秒發(fā)送一次數(shù)據(jù)。esp_now_send返回是否發(fā)送出去,回調(diào)函數(shù)中展示是否成功發(fā)送給接收方。

#include?<esp_now.h>
#include?<WiFi.h>

//?REPLACE?WITH?YOUR?RECEIVER?MAC?Address
uint8_t?broadcastAddress[]?=?{0x8C,?0xCE,?0x4E,?0xA6,?0x73,?0x74};

//?Structure?example?to?send?data
//?Must?match?the?receiver?structure
typedef?struct?struct_message?{
??char?a[32];
??int?b;
??float?c;
??bool?d;
}?struct_message;

//?Create?a?struct_message?called?myData
struct_message?myData;

esp_now_peer_info_t?peerInfo;

//?callback?when?data?is?sent
void?OnDataSent(const?uint8_t?*mac_addr,?esp_now_send_status_t?status)?{
??Serial.print("rnLast?Packet?Send?Status:t");
??Serial.println(status?==?ESP_NOW_SEND_SUCCESS???"Delivery?Success"?:?"Delivery?Fail");
}
?
void?setup()?{
??//?Init?Serial?Monitor
??Serial.begin(115200);
?
??//?Set?device?as?a?Wi-Fi?Station
??WiFi.mode(WIFI_STA);

??//?Init?ESP-NOW
??if?(esp_now_init()?!=?ESP_OK)?{
????Serial.println("Error?initializing?ESP-NOW");
????return;
??}

??//?Once?ESPNow?is?successfully?Init,?we?will?register?for?Send?CB?to
??//?get?the?status?of?Trasnmitted?packet
??esp_now_register_send_cb(OnDataSent);
??
??//?Register?peer
??memcpy(peerInfo.peer_addr,?broadcastAddress,?6);
??peerInfo.channel?=?0;??
??peerInfo.encrypt?=?false;
??
??//?Add?peer????????
??if?(esp_now_add_peer(&peerInfo)?!=?ESP_OK){
????Serial.println("Failed?to?add?peer");
????return;
??}
}
?
void?loop()?{
??//?Set?values?to?send
??strcpy(myData.a,?"THIS?IS?A?CHAR");
??myData.b?=?random(1,20);
??myData.c?=?1.2;
??myData.d?=?false;
??
??//?Send?message?via?ESP-NOW
??esp_err_t?result?=?esp_now_send(broadcastAddress,?(uint8_t?*)?&myData,?sizeof(myData));
???
??if?(result?==?ESP_OK)?{
????Serial.println("Sent?with?success");
??}
??else?{
????Serial.println("Error?sending?the?data");
??}
??delay(2000);
}

完整接收程序

接收跟發(fā)送差不多,也是要定義一個跟發(fā)送方一樣的數(shù)據(jù)結(jié)構(gòu)體,用于保存接收到的數(shù)據(jù),創(chuàng)建一個接收回調(diào)函數(shù),當(dāng)接收到數(shù)據(jù)時,調(diào)用此函數(shù),將數(shù)據(jù)保存到一個結(jié)構(gòu)體變量中,然后打印出來。

#include?<esp_now.h>
#include?<WiFi.h>

//?Structure?example?to?receive?data
//?Must?match?the?sender?structure
typedef?struct?struct_message?{
????char?a[32];
????int?b;
????float?c;
????bool?d;
}?struct_message;

//?Create?a?struct_message?called?myData
struct_message?myData;

//?callback?function?that?will?be?executed?when?data?is?received
void?OnDataRecv(const?uint8_t?*?mac,?const?uint8_t?*incomingData,?int?len)?{
??memcpy(&myData,?incomingData,?sizeof(myData));
??Serial.print("Bytes?received:?");
??Serial.println(len);
??Serial.print("Char:?");
??Serial.println(myData.a);
??Serial.print("Int:?");
??Serial.println(myData.b);
??Serial.print("Float:?");
??Serial.println(myData.c);
??Serial.print("Bool:?");
??Serial.println(myData.d);
??Serial.println();
}
?
void?setup()?{
??//?Initialize?Serial?Monitor
??Serial.begin(115200);
??
??//?Set?device?as?a?Wi-Fi?Station
??WiFi.mode(WIFI_STA);

??//?Init?ESP-NOW
??if?(esp_now_init()?!=?ESP_OK)?{
????Serial.println("Error?initializing?ESP-NOW");
????return;
??}
??
??//?Once?ESPNow?is?successfully?Init,?we?will?register?for?recv?CB?to
??//?get?recv?packer?info
??esp_now_register_recv_cb(OnDataRecv);
}
?
void?loop()?{

}

將上面的發(fā)送與接收程序燒錄到兩塊板,就實(shí)現(xiàn)了數(shù)據(jù)的單向傳輸,我們看下接收方的串口打印數(shù)據(jù):

這是最簡單的一個案例,大家對ESP-NOW先有一個簡單的理解,關(guān)于ESP-NOW的管理設(shè)備,刪除設(shè)備,掃描從設(shè)備,自動配對等,下一期再講,布置個作業(yè),大家可以在發(fā)送端添加一個按鈕,接收端添加一個LED等,就可以實(shí)現(xiàn)一個遙控器的Demo了,快去嘗試一下吧。

下一節(jié),我們會實(shí)際做一個小項(xiàng)目,增加以下功能:

  • 多個主機(jī),多個從機(jī);從機(jī)按鍵長按觸發(fā)下進(jìn)入廣播模式,釋放出WIFI信號,主機(jī)在上電的時候,會掃描到WIFI信號并自動配對;配對完成之后,主機(jī)從機(jī)都會將MAC地址自動寫入存儲空間,下次啟動就不用重新配對;兩個從機(jī)可以通過按鍵控制主機(jī)上的兩個LED燈,主機(jī)也可以同時控制兩個從機(jī)上的LED燈;兩個從機(jī)分別采集溫度濕度氣壓數(shù)據(jù),傳給主機(jī);主機(jī)將數(shù)據(jù)在本地顯示屏顯示出來,同時在連接WiFi之后,可以通過Web端實(shí)時查看傳感器數(shù)據(jù);指示燈顯示連接狀態(tài)。

感謝大家,關(guān)于ESP32的學(xué)習(xí),希望大家Enjoy!

參考資料:

1、https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/api-reference/network/esp_now.html

2、https://randomnerdtutorials.com/esp-now-esp32-arduino-ide/

3、https://github.com/espressif/esp-now

推薦器件

更多器件
器件型號 數(shù)量 器件廠商 器件描述 數(shù)據(jù)手冊 ECAD模型 風(fēng)險等級 參考價格 更多信息
AD1838AASZ-REEL 1 Rochester Electronics LLC SPECIALTY CONSUMER CIRCUIT, PQFP52, LEAD FREE, PLASTIC, MS-022-AC, MQFP-52
暫無數(shù)據(jù) 查看
TPA3220DDW 1 Texas Instruments 60-W stereo, 110-W mono, 7- to 32-V, analog input Class-D audio amplifier w/ low idle, pad-down 44-HTSSOP -40 to 85

ECAD模型

下載ECAD模型
$1.94 查看
LM386N-1/NOPB 1 National Semiconductor Corporation IC 0.325 W, 1 CHANNEL, AUDIO AMPLIFIER, PDIP8, DIP-8, Audio/Video Amplifier
$1.85 查看

相關(guān)推薦

電子產(chǎn)業(yè)圖譜

最全電子漫畫收集達(dá)人,漫畫控必選!用文字和圖片帶你領(lǐng)略電子世界之美。 由曉宇哥哥操刀的芯片之家公眾號,提供45萬個Symbol和3D封裝庫免費(fèi)下載,定期分享軟硬件、物聯(lián)網(wǎng)類技術(shù)知識外,還精心整理大量參考設(shè)計和文檔資源,電路圖和源代碼資料供下載。 立即打開“芯片之家 ”,感受電子與藝術(shù)的完美結(jié)合。