در اپیزودهای قبلی از ESP-NOW سناریو های مختلفی را تست کردیم، که شامل انتقال دیتای ماژول و سنسور های مختلفی بود. در این پروژه قصد داریم به کمک پروتکل ESP-Now مقادیر x را از ماژول MPU6050 دریافت و در مقصد به این طریق یک را نسبت به تغییر مقادیر x سروو موتور را کنترل کنیم. به عبارتی پروژه کنترل سرو موتور با ژایرو توسط ESP-Now را پیاده کنیم. در ادامه این آموزش با مرجع تخصصی آردوینو به زبان فارسی، دیجی اسپارک همراه باشید.
پروتکل ESP-Now
ESP-NOW یک پروتکل ارتباطی بی سیم است که توسط Espressif ساخته شده و دارای قابلیت انتقال پکت است. این پروتکل چندین دستگاه را قادر می سازد تا به روشی آسان با یکدیگر صحبت کنند و اطلاعات را بصورت بهینه بین یکدیگر انتقال دهند. این پروتکل مشابه اتصال بی سیم ۲٫۴GHz است، که اغلب در ماوس های بی سیم استفاده می شود. بنابراین، جفت شدن دستگاه ها قبل از برقراری ارتباط لازم است. این به این معنی است که پس از جفت شدن دستگاه ها با یکدیگر، اتصال پایدار است. به عبارت دیگر، اگر بطور ناگهانی یکی از ESP های شما قطع شود یا ریست شود، هنگام راه اندازی مجدد بطور خودکار اتصال برقرار می شود.
مزیت های پروتکل ESP-NOW
- انتقال داده تا ۲۵۰ بایت.
- بهره مندی از ارتباط رمزگذاره شده.
-
استفاده از Call Back برای اطلاع رسانی به لایه های مختلف در صورت موفقیت یا عدم موفقیت در انتقال داده.
محدودیت های پروتکل ESP-NOW
- حدکثر محدوده ۲۵۰payload بایت.
- حداکثر پشتیبانی از ۱۰عدد SoftAP رمزگذاری شده.
- حداکثر تعداد پشتیباتی در حالت رمزگذاری نشده ۲۰ عدد.
نقش فرستنده و گیرنده
در پروژه کنترل سرو موتور با ژایرو فرستنده که برد nodemcu ما با تراشه ESP32 هست وظیفه بدست آموردن مقادیر محور x از ماژول mpu6050 و ارسال آن به سمت گیرنده توسط پروتکل ESP-NOW. و در قسمت دیگر از پروژه یعنی گیرنده ما که برای این مورد یک برد Wemos در نظر گرفتیم تا دیتای ارسال شده دریافت و برای فرمان دهی به سروو موتور SG90 تحلیل شود.
برد Wemos
برد Wemos یکی از پرطرافدار ترین برد هایی است که در زمینه iot مورد استفاده قرار میگیرد، یکی از مزیت های این برد نسبت به برد هایی مانند Node MCU اندازه کوچک آن می باشد تراشه وای فای مورد استفاده در این برد ESP8266 می باشد. از دیگر مزیت های این برد وجود شیلد های مختلفی برای این برد می باشد، که انجام هر پروژه ای را برای کاربر بسیار آسان و لذت بخش می کند، شیلد هایی از جمله شیلد باتری، multi sensor ، DHT22 ، رله ، oled تعداد بسیار زیادی شیلد برای این برد توسعه داده شده که در نتیجه تجربه خوبی از iot برای شما به جا خواهد گذاشت. در پروژه کنترل سرو موتور با ژایرو برد ویموس به عنوان گیرنده و انتقال دیتا به سرو موتور عمل میکند.
برد ESP32
ESP32 نسل پیشرفته ESP8266 است. یکی از تفاوتهای آن بلوتوث داخلیاش میباشد. همچنین دارای هسته وایفای ۲,۴ گیگا هرتزی و بلوتوث داخلی تولید شده با تکنولوژی ۴۰ نانومتری شرکت TSMC میباشد. این ماژول دارای بهترین پرفورمنس در مصرف انرژی میباشد یعنی با کمترین مصرف انرژی بهترین نتیجه را برای ما به همراه دارد. اگر بخواهیم دقیقتر به این برد نگاه کنیم باید بگوییم که این یک chip است که پلتفرم NodeMCU در اون پیاده سازی شده که به این نوع چیپ ها System on a chip microcontrollers هم گفته میشود.
روش کار این پروژه
در پروژه کنترل سرو موتور با ژایرو به دلیل یک طرفه بودن انتقال دیتا یکی از برد های وایفای به عنوان Master و برد دوم با عوان Slave کار خواهد کرد، که در نتیجه دیتا تنها یک برد به برد دیگر ارسال خواهد شد. در این سناریو برد ارسال کننده یا Master برد ESP32 است و برد Slave یا دریافت کننده برد Wemos که از تراشه ESP8266 استفاده خواهد کرد.
وسایل مورد نیاز
برد ESP برپایه تراشه ESP8266 یا ESP32
کابل جامپر مخصوص اتصالات سنسور و بردها
نصب کتابخانه مرجع
در این بخش اقدام به نصب کتابخانه مرجع ESP-NOW خواهیم کرد تا در نتیجه این امکان فراهم شود که از توابع و دستورات مورد نیاز در کد پروژه استفاده کنیم. در صورت دریافت هرگونه ارور مبنی بر عدم وجود کتابخانه espnow.h طبق مراحل زیر پیش بروید.
- این مسیر را دنبال کنید Sketch > Include Library > Manage Libraries
- کلمه espnow را جستجو کنید.
- کتابخانه را نصب کنید.
بدست آوردن مک آدرس ESP32
پیش از این در آموزش راه اندازی پروتکل ESP-Now روش بدست آوردن مک آدرس را توضیح دادیم. چنانچه این مورد را اطلاعی ندارید، کافیست به پست اشاره شده مراجعه کنید. برای اجرای پروژه مبتنی بر پروتکل ESP-Now بایستی حتما حتما مک آدرس برد ESP مورد استفاده را بدست بیاوریم. برای این منظور بایستی اقداماتی را انجام دهیم. که این مورد در پست قبلی کاملا توضیح داده شده است.
کد و شماتیک بخش فرستنده
در اولین بخش از راهاندازی پروژه بعد از نصب کتابخانه های مورد نیاز اقدام به برقراری اتصالات خواهیم کرد در برد ESP32 اتصالات برای ماژول ژایرو به این شکل است از پین های D21 و D22 برای برقراری اتصال i2c با MPU6050 استفاده خواهیم کرد. اتصالات را طبق جدول و شماتیک زیر برقرار کنید.
- اتصالات بخش فرستنده پروژه کنترل سروو موتور از راه دور با پروتکل ESP-NOW
در ادامه نویت به آپلود کد ها در برد ESP32 میرسد. البته ابتدا بخش های مهمی از این کد را بررسی خواهیم کرد. ابتدا ساختار دیتای مد نظر را اینجاد خواهیم کرد تا مقادیر x را ارسال کنیم.
typedef struct test_struct { int x; float y; float z; } test_struct;
در این بخش دیتای خروجی از mpu6050 را در مقادیر زیر ذخیره خواهیم کرد، که در ادامه از آن ها استفاده کنیم.
MPU6050 accelgyro; int16_t ax, ay, az; int16_t gx, gy, gz;
در این بخش یک Void ایجاد کردیک که وظیفه ساخت payload برای ارسال را دارد.
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) { char macStr[18];
کد کامل بخش فرستنده پروژه کنترل سروو موتور از راه دور با پروتکل ESP-NOW
#include <esp_now.h> #include <WiFi.h> #include <SPI.h> #include "I2Cdev.h" #include "MPU6050.h" MPU6050 accelgyro; int16_t ax, ay, az; int16_t gx, gy, gz; #define OUTPUT_READABLE_ACCELGYRO uint8_t broadcastAddress1[] = {0xBC,0xDD,0xC2,0xB3,0xC4,0xC2}; typedef struct test_struct { int x; float y; float z; } test_struct; test_struct test; void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) { char macStr[18]; Serial.print("Packet to: "); // Copies the sender mac address to a string snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); Serial.print(macStr); Serial.print(" send status:\t"); Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail"); } void setup() { Serial.begin(115200); #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE Wire.begin(); #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE Fastwire::setup(400, true); #endif accelgyro.initialize(); WiFi.mode(WIFI_STA); if (esp_now_init() != ESP_OK) { Serial.println("Error initializing ESP-NOW"); return; } esp_now_register_send_cb(OnDataSent); esp_now_peer_info_t peerInfo; peerInfo.channel = 0; peerInfo.encrypt = false; memcpy(peerInfo.peer_addr, broadcastAddress1, 6); if (esp_now_add_peer(&peerInfo) != ESP_OK){ Serial.println("Failed to add peer"); return; } } void loop() { accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz); test.x = random(ax); test.y = random(ay); test.z = random(az); esp_err_t result = esp_now_send(0, (uint8_t *) &test, sizeof(test_struct)); if (result == ESP_OK) { Serial.println("Sent with success"); } else { Serial.println("Error sending the data"); } delay(500); }
کد و شماتیک بخش گیرنده
در بخش بعدی برای راهاندازی برد دریافت کننده مانند بخش قبل ابتدا با استفاده از جدول و شماتیک زیر اتصالات را برقرار کنید. در این بخش از یکی از پین های PWM در برد Wemos برای راهاندازی سروو موتور SG90 استفاده خواهیم کرد و مقادیر بدست آمده را
- اتصالات بخش گیرنده پروژه کنترل سروو موتور از راه دور با پروتکل ESP-NOW
در خطوط ابتدایی کد ابتدا یک متغیر برای سروو SG90 مشخص میکنیم. در ادامه ساختار دیتای دریافتی را مشخص میکنیم که در این ساختار از int استفاده کرده ایم.
Servo sg90; //Servo sg90two; typedef struct temp_struct { int x; // float y; // float z; } temp_struct;
در این قسمت مقادیر x ذخیره شده در myData را را در سریال مانیتور print میکنیم.
Serial.print("X= "); Serial.println(myData.x);
در این خط پایه مربوط برای کنترل سروو را مشخص میکنیم.
sg90.attach (D2);
در نهایت مقادیر دریافت شده را ابتدا رنج مورد استفاده را مشخص و در نهایت فرمان را به سروو میدهیم.
myData.x = map (myData.x, -1700, 1700, 0, 100) ; // myData.y = map (myData.y, -17000, 17000, 0, 180) ; sg90.write (myData.x); // sg90two.write (myData.y);
کد کامل بخش گیرنده پروژه کنترل سروو موتور از راه دور با پروتکل ESP-NOW
#include <ESP8266WiFi.h> #include <espnow.h> #include <Servo.h> Servo sg90; //Servo sg90two; typedef struct temp_struct { int x; // float y; // float z; } temp_struct; temp_struct myData; void OnDataRecv(uint8_t * mac, uint8_t *incomingData, uint8_t len) { memcpy(&myData, incomingData, sizeof(myData)); Serial.print("Bytes received: "); Serial.println(len); Serial.print("X= "); Serial.println(myData.x); //Serial.print("Y= "); //Serial.println(myData.y); //Serial.print("Z= "); //Serial.println(myData.z); Serial.println(); } void setup() { Serial.begin(115200); sg90.attach (D2); //sg90two.attach (D3); WiFi.mode(WIFI_STA); if (esp_now_init() != 0) { Serial.println("Error initializing ESP-NOW"); return; } esp_now_set_self_role(ESP_NOW_ROLE_SLAVE); esp_now_register_recv_cb(OnDataRecv); } void loop() { myData.x = map (myData.x, -1700, 1700, 0, 100) ; // myData.y = map (myData.y, -17000, 17000, 0, 180) ; sg90.write (myData.x); // sg90two.write (myData.y); delay (500); }
جمع بندی
در این پروژه مقادیر ماژول ژایرو MPU6050 را تحلیل و به سمت برد دوم ارسال کردیم و در نتیجه توانستیم سروو موتور را در مقصد کنترل کنیم. از این پروژه در مواردی که نیاز به کنترل حرکتی در پروژه ای نیاز باشد اما بدون اتصال فیزیکی میتوانیم استفاده کنیم و البته سناریو های مختلفی را برای اینگونه پروژه ها میتوان اعمال کرد.
چنانچه در مراحل راه اندازی و انجام این پروژه با مشکل مواجه شدید، بدون هیچ نگرانی در انتهای همین پست، به صورت ثبت نظر سوالتان را مطرح کنید. من در سریعترین زمان ممکن پاسخ رفع مشکل شما را خواهم داد. همچنین اگر ایرادی در کدها و یا مراحل اجرایی وجود دارند میتوانید از همین طریق اطلاع رسانی کنید.
در پایان نظرات و پیشنهادات خود را با ما درمیان بگذارید و با اشتراک گذاری این آموزش در شبکه های اجتماعی , از وبسایت دیجی اسپارک حمایت کنید.
سلام .
کد در قسمت فرستنده این ارور رو میده :
Arduino: 1.8.13 (Windows 10), Board: “NodeMCU 1.0 (ESP-12E Module), 80 MHz, Flash, Legacy (new can return nullptr), All SSL ciphers (most compatible), 4MB (FS:2MB OTA:~1019KB), 2, v2 Lower Memory, Disabled, None, Only Sketch, 115200”
espnow_send:21:42: error: ‘esp_now_send_status_t’ has not been declared
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
^
espnow_send:21:42: error: ‘esp_now_send_status_t’ has not been declared
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
^
F:\arduino projects\espnow_send\espnow_send.ino: In function ‘void OnDataSent(const uint8_t*, int)’:
espnow_send:29:28: error: ‘ESP_NOW_SEND_SUCCESS’ was not declared in this scope
Serial.println(status == ESP_NOW_SEND_SUCCESS ? “Delivery Success” : “Delivery Fail”);
^
F:\arduino projects\espnow_send\espnow_send.ino: In function ‘void setup()’:
espnow_send:37:8: error: ‘class WiFiClass’ has no member named ‘mode’
WiFi.mode(WIFI_STA);
^
espnow_send:37:13: error: ‘WIFI_STA’ was not declared in this scope
WiFi.mode(WIFI_STA);
^
espnow_send:43:25: error: ‘ESP_OK’ was not declared in this scope
if (esp_now_init() != ESP_OK) {
^
espnow_send:48:38: error: invalid conversion from ‘void (*)(const uint8_t*, int) {aka void (*)(const unsigned char*, int)}’ to ‘esp_now_send_cb_t {aka void (*)(unsigned char*, unsigned char)}’ [-fpermissive]
esp_now_register_send_cb(OnDataSent);
^
In file included from F:\arduino projects\espnow_send\espnow_send.ino:1:0:
C:\Users\ASUS-R\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4/tools/sdk/include/espnow.h:47:5: error: initializing argument 1 of ‘int esp_now_register_send_cb(esp_now_send_cb_t)’ [-fpermissive]
int esp_now_register_send_cb(esp_now_send_cb_t cb);
^
espnow_send:50:3: error: ‘esp_now_peer_info_t’ was not declared in this scope
esp_now_peer_info_t peerInfo;
^
espnow_send:50:23: error: expected ‘;’ before ‘peerInfo’
esp_now_peer_info_t peerInfo;
^
espnow_send:51:3: error: ‘peerInfo’ was not declared in this scope
peerInfo.channel = 0;
^
espnow_send:54:38: error: ‘ESP_OK’ was not declared in this scope
if (esp_now_add_peer(&peerInfo) != ESP_OK){
^
F:\arduino projects\espnow_send\espnow_send.ino: In function ‘void loop()’:
espnow_send:79:3: error: ‘esp_err_t’ was not declared in this scope
esp_err_t result = esp_now_send(0, (uint8_t *) &test, sizeof(temp_struct));
^
espnow_send:79:13: error: expected ‘;’ before ‘result’
esp_err_t result = esp_now_send(0, (uint8_t *) &test, sizeof(temp_struct));
^
espnow_send:81:7: error: ‘result’ was not declared in this scope
if (result == ESP_OK) {
^
espnow_send:81:17: error: ‘ESP_OK’ was not declared in this scope
if (result == ESP_OK) {
^
Multiple libraries were found for “DHT.h”
Used: C:\Users\ASUS-R\Documents\Arduino\libraries\DHT_sensor_library
Not used: C:\Users\ASUS-R\Documents\Arduino\libraries\DHT_sensor_library-1.4.1
exit status 1
‘esp_now_send_status_t’ has not been declared
This report would have more information with
“Show verbose output during compilation”
option enabled in File -> Preferences.
سلام، بنظر نرمافزار دو کتابخانه برای سنسور DHT11 تشخیص داده، یکی از کتابخانه ها را حذف کنید، در ضمن از صحت مدل برد هم اطمینان حاصل کنید.