مینی ریموت کنترل بیسیم با برد ESP32 و جویاستیک
ریموت کنترلها ابزارهای بهشدت کاربردی برای هدایت رباتها و پروژههای اینترنت اشیا هستن، اما خیلی وقتها ابعاد بزرگ و جاگیرشون باعث میشه حملونقلشون تو پروژههای مینیمال سخت باشه. تو این آموزش از آیسیمدار، میخوایم یه ریموت کنترل بیسیم فوقالعاده جمعوجور و جیبی بسازیم که با استفاده از یه برد قدرتمند و یه ماژول جویاستیک مینیاتوری به راحتی تو مشت جا میشه.
این مینی ریموت برای ارتباط بیسیم از پروتکل خفن ESP-NOW استفاده میکنه که برد ارتباطی خیلی بالایی داره و میتونی باهاش انواع ربات، ماشین کنترلی یا حتی سیستمهای هوشمند رو از فواصل دور به راحتی کنترل کنی. یکی از مزیتهای عالی این پروژه اینه که خود برد میکروکنترلر مدار شارژ باتری داره، یعنی نیازی به ماژولهای اضافه برای شارژ باتری لیتیومی نداریم و مدارمون حسابی خلوت و تمیز درمیاد.
مدار اصلی از یه برد وایفایدار مینی، یه باتری لیتیوم پلیمر و یه ماژول جویاستیک ساده تشکیل شده. پس هویه رو داغ کن و وسایلت رو روی میز بچین تا با هم این گجت کوچیک و حرفهای رو بسازیم. بریم سراغ ساخت!
قطعات موردنیاز
- برد XIAO ESP32-C6 (یا بردهای مشابه مجهز به باتریشارژر)
- ماژول مینی جویاستیک (آنالوگ)
- باتری لیتیوم پلیمر کوچیک (مثل مدلهای 100mAh)
- کلید قطع و وصل مینیاتوری
- سیمهای نازک لاکی یا سیلیکونی
- قاب پرینت سهبعدی یا جعبه مقوایی برای بدنه
لحیمکاری و سیمکشی قطعات
مدار این پروژه خیلی ساده و سرراسته. اول از همه باید کانکتورهای باتری رو به پدهای زیر برد ESP-C6 لحیم کنیم. برای تمیزی کار بهتره از سوکتهای مینیاتوری استفاده کنی تا در صورت نیاز باتری به راحتی جدا بشه.
یادت باشه هیچوقت سیمهای باتری رو مستقیما به خود برد لحیم نکنی، چون ممکنه موقع کار اتصالی کنه و قطعات آسیب ببینن. همونطور که گفتیم خود برد ESP32-C6 به عنوان ماژول شارژر باتری عمل میکنه. فقط کافیه یه کلید قطع و وصل تو مسیر باتری قرار بدی تا بتونی ریموت رو راحت خاموش و روشن کنی و از هدر رفتن شارژ جلوگیری بشه.
چون داریم از باتری استفاده میکنیم، روی پین 5 ولت میکروکنترلر ولتاژی نداریم. برای همین، باید پین VCC جویاستیک رو مستقیم به پین 3.3 ولت برد وصل کنیم. اتصالات جویاستیک رو به این شکل انجام بده: پین VCC به 3.3 ولت، پین GND به GND، محور X به پین D1، محور Y به پین D2 و کلید جویاستیک (Button) رو به پین A0 لحیم کن.
البته دستت کاملا بازه که این پینها رو تو کدنویسی تغییر بدی و هر جور که مدارت بهتر جمع میشه سیمکشی کنی.
برنامهنویسی بردهای فرستنده و گیرنده
بخش فرستنده: نرمافزار این ریموت از پروتکل ESP-NOW روی بستر وایفای استفاده میکنه. این پروتکل خیلی سبک و سریعه و معمولا برد ارتباطیش از شبکههای وایفای معمولی با اون پروتکلهای پیچیدهشون خیلی بیشتره. تو یه تست ساده میتونی تا مسافت بیشتر از 95 متر هم به راحتی جواب بگیری که برای یه ریموت به این کوچیکی فوقالعادهست!
قبل از آپلود کدهای اصلی، اول باید مک آدرس (MAC Address) برد گیرنده رو پیدا کنی تا فرستنده بدونه دقیقا باید دیتا رو به کی بفرسته. یه کد ساده برای خوندن مک آدرس روی برد گیرنده آپلود کن، آدرس رو یادداشت کن و بعدش همون آدرس رو تو کدهای اصلی بخش فرستنده قرار بده.
کدهای فرستنده وظیفه دارن مقادیر حرکتی جویاستیک و وضعیت دکمه اون رو به صورت مداوم بخونن و ارسال کنن. اگه بخوای مصرف باتری رو پایین بیاری تا ریموتت مدت زمان خیلی بیشتری شارژ نگه داره، میتونی تو کدهات از قابلیت خواب عمیق (Sleep Mode) هم استفاده کنی.
/*
===================
Markus Opitz 2026
instructables.com
===================
ESP-NOW Transmitter
*/
#include <WiFi.h>
#include <esp_now.h>
// ================== adjust! ==================
uint8_t receiverMac[] = { 0x__, 0x__, 0x__, 0x__, 0x__, 0x__ };
// ==============================================
#define JOY_X_PIN A1
#define JOY_Y_PIN A2
#define BTN_PIN D0
// Schwellen
const int center = 1650;
const int deadzone = 100;
// Datenstruktur
typedef struct {
uint16_t servo;
bool left;
bool right;
bool button;
} ControlData;
ControlData data;
void setup() {
Serial.begin(115200);
pinMode(BTN_PIN, INPUT_PULLUP);
WiFi.mode(WIFI_STA);
if (esp_now_init() != ESP_OK) {
Serial.println("ESP-NOW init fail");
return;
}
esp_now_peer_info_t peerInfo = {};
memcpy(peerInfo.peer_addr, receiverMac, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
esp_now_add_peer(&peerInfo);
Serial.println("transmitter ready");
}
void loop() {
int x = analogRead(JOY_X_PIN);
int y = analogRead(JOY_Y_PIN);
if (abs(y - center) < deadzone) {
x = center;
}
data.servo = map(y, 0, 3280, 0, 180);
data.servo = constrain(data.servo, 0, 180);
data.left = (x < center - deadzone);
data.right = (x > center + deadzone);
data.button = (digitalRead(BTN_PIN) == LOW);
//Serial.print(x); Serial.print(" ");
Serial.print(y);
if (digitalRead(BTN_PIN) == LOW) Serial.print(" button");
Serial.println("");
/*
if (x<-10) Serial.println(" <--");
if (x>10) Serial.println(" -->");
if (y>10) Serial.println(" ^ ");
if (y<-10) Serial.println(" ~ ");
*/
esp_now_send(receiverMac, (uint8_t*)&data, sizeof(data));
delay(30); // ~33 Hz
}
بخش گیرنده: تو این سمت (که ما باز هم از یه برد ESP32-C6 استفاده کردیم) سیگنالها دریافت میشن و به دستورات فیزیکی یا کنترلی تبدیل میشن. برای تست عملکرد مدار تو سمت گیرنده، یه سرووموتور (برای حرکت بالا و پایین) و یه الایدی با مقاومت 220 اهم وصل شده. البته این فقط یه نمونه است و تو میتونی هر ماژول یا قطعهای که برای پروژهت نیاز داری رو به گیرنده وصل کنی.
/*
===================
Markus Opitz 2026
instructables.com
===================
ESP-NOW Receiver
*/
#include <WiFi.h>
#include <esp_now.h>
// Data structure (MUST be identical!)
typedef struct {
uint16_t servo;
bool left;
bool right;
bool button;
} ControlData;
ControlData data;
#include <ESP32Servo.h>
Servo R1;
const int servoPinR1 = D2;
int currentAngle = 90;
const int LEDpin = D7;
bool lastButtonState = false;
void onReceive(const esp_now_recv_info *info,
const uint8_t *incomingData,
int len) {
ControlData data;
memcpy(&data, incomingData, sizeof(data));
R1.write(data.servo);
Serial.println(data.servo);
if (data.left) {Serial.print("LEFT "); }
if (data.right) {Serial.print("RIGHT "); }
if (data.button && !lastButtonState) {
Serial.println("button");
digitalWrite(LEDpin, HIGH);
}
if (!data.button && lastButtonState) {
digitalWrite(LEDpin, LOW);
}
lastButtonState = data.button;
Serial.println();
}
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
if (esp_now_init() != ESP_OK) {
Serial.println("ESP-NOW init failed");
return;
}
esp_now_register_recv_cb(onReceive);
Serial.println("receiver ready");
// ESP32-C6 PWM Setup
R1.setPeriodHertz(50); // 50 Hz for Servos
R1.attach(servoPinR1, 500, 2400);
R1.write(90); delay(10);
Serial.println("servo ready");
pinMode(LEDpin, OUTPUT);
digitalWrite(LEDpin, LOW);
}
void loop() {
// all happens in callback
}
ارتباط از طریق بلوتوث (راهکار جایگزین)
اگه دوست داشته باشی، میتونی کدهات رو طوری تغییر بدی که ارتباط بین فرستنده و گیرنده از طریق سیگنالهای بلوتوث کممصرف (BLE) برقرار بشه. تو این حالت سختافزار و سیمکشیها دقیقا همون شکلی باقی میمونه، فقط باید در نظر داشته باشی که تو حالت بلوتوث برد ارتباطی مدار یه مقدار کمتر از پروتکل قبلی میشه.
مونتاژ قطعات داخل قاب ریموت
برای ساخت بدنه ریموت میتونی از چوب، مقوا یا یه جعبه پلاستیکی آماده استفاده کنی. اما برای اینکه دستگاه کاملا جمعوجور و تمیز بشه، من یه قاب اختصاصی رو تو نرمافزار طراحی کردم و با پرینتر سهبعدی چاپش کردم. در این قاب کاملا کیپ میشه و حتی نیازی به هیچ چفت و پیچی برای بستنش نداره.
قبل از قرار دادن قطعات تو قاب، تمام اتصالات رو با سیمهای کوتاه لحیم کن تا فضای داخل محفظه الکی اشغال نشه. چون مدار جریان زیادی نمیکشه، استفاده از سیمهای خیلی نازک هم کاملا جوابه. بعدش سرپوش مشکی و فابریک جویاستیک رو در بیار تا راحتتر تو قاب جا بگیره. حواست باشه که آنتن رو حتما به برد ESP32 وصل کنی تا برد ارتباطیت افت نکنه.
در نهایت، قطعات رو خیلی ظریف و با یه مقدار کم چسب حرارتی سر جای خودشون محکم کن تا موقع تکون دادن ریموت، قطعات داخلش جابهجا نشن.
طراحی سرپوش کاستوم برای جویاستیک
برای اینکه ریموت کنترل ما تا حد امکان کوچیک و باریک بشه، یه سرپوش سادهتر و مینیاتوری برای جویاستیک طراحی کردم. فقط کافیه این قطعه رو پرینت بگیری، روی پین فلزی جویاستیک فشارش بدی و با یه قطره چسب محکمش کنی. همین کار ساده ظاهر ریموتت رو خیلی حرفهایتر و کاربردیتر میکنه.
جمعبندی و تست نهایی مینی ریموت
فایلهای پیوست
تو میتونی اولین سازنده باشی!
اگه پروژه رو ساختی به اشتراک بزار و اعتبار هدیه بگیر
این آموزش با استانداردهای اختصاصی آیسیمدار بازنویسی و بهینهسازی شده و تمامی حقوق انتشار آن متعلق به این مجموعه است و در صورت کپی یا بازنشر پیگرد قانونی خواهد داشت.








































گفتگوهای کاربران
هنوز نظری ثبت نشده؛ تو شروع کن!
هنوز نظری ثبت نشده؛ تو شروع کن!