🦾 راه‌اندازی سروو موتور با ESP32: کتابخانه‌ی ESP32Servo، روش ledc ۵۰ هرتز و تغذیه‌ی درست

✍️ تیم ووکوی فارسی ·

اگر قبلاً با آردوینو اونو سروو چرخانده باشی، احتمالاً اولین تلاشت با ESP32 با یک خطا تمام شده است: کتابخانه‌ی Servo.h می‌گوید فقط بردهای AVR را پشتیبانی می‌کند. خبر خوب این است که راه‌اندازی سروو با ESP32 با یک کتابخانه‌ی دیگر دقیقاً به همان سادگی است و حتی بدون کتابخانه، با واحد PWM خود ESP32 هم می‌شود. در این آموزش هر دو روش را یاد می‌گیریم، سروو را با یک پتانسیومتر کنترل می‌کنیم و مهم‌تر از همه، یاد می‌گیریم سروو را درست تغذیه کنیم تا برد وسط کار ریست نشود. کد اصلی را در شبیه‌ساز ESP32، به همان سبکی که در ووکوی (Wokwi) کار می‌کنی، اجرا می‌کنیم.

سروو چطور زاویه را می‌فهمد؟

سروو موتور یک موتور کوچک با چرخ‌دنده و یک مدار کنترل داخلی است. سیم سیگنال آن هر ۲۰ میلی‌ثانیه (یعنی ۵۰ بار در ثانیه، ۵۰ هرتز) یک پالس می‌گیرد و طول همین پالس زاویه را تعیین می‌کند: حدود ۵۰۰ میکروثانیه یعنی صفر درجه، ۱۵۰۰ میکروثانیه یعنی وسط (۹۰ درجه) و حدود ۲۴۰۰ میکروثانیه یعنی ۱۸۰ درجه. این عددها بین مدل‌ها کمی فرق دارند. پس هر روشی که بتواند یک پالس ۵۰ هرتزی با طول دقیق بسازد، می‌تواند سروو را بچرخاند. این همان PWM است، فقط با فرکانس خیلی پایین. اگر فرق سروو با موتور معمولی برایت روشن نیست، سروو یا موتور DC؟ را بخوان.

قطعه‌ها و سیم‌کشی

ازبه ESP32توضیح
سیم قهوه‌ای یا مشکی سرووGNDزمین مشترک؛ هرگز فراموشش نکن
سیم قرمز سرووVIN۵ ولت USB؛ نه 3V3
سیم نارنجی یا زرد سرووGPIO18سیگنال؛ پایه‌ی امن و بدون نقش در بوت
پایه‌ی کناری پتانسیومتر3V3ولتاژ مرجع ADC
پایه‌ی وسط پتانسیومترGPIO34ورودی آنالوگ روی ADC1
پایه‌ی کناری دیگر پتانسیومترGND

چرا GPIO18 و GPIO34؟ اولی هیچ کار خاصی هنگام بوت نمی‌کند و دومی بهترین پایه‌ی آنالوگ است. منطق انتخاب پایه‌ها را در پین اوت ESP32 نوشته‌ایم.

روش ۱: کتابخانه‌ی ESP32Servo (پیشنهادی)

در آردوینو IDE از منوی Tools گزینه‌ی Manage Libraries را باز کن، ESP32Servo را جست‌وجو کن و نصبش کن. این کتابخانه از واحد ledc خود ESP32 استفاده می‌کند ولی دستورهایش همان attach و write آشناست. اگر هسته‌ی ESP32 نسخه‌ی ۳ داری، ESP32Servo هم باید نسخه‌ی ۳ یا جدیدتر باشد.

// ESP32 + servo: the knob sets the angle (ESP32Servo library).
#include <ESP32Servo.h>

const int SERVO_PIN = 18;   // any output pin that is not a strapping pin
const int POT = 34;         // ADC1, input-only

Servo arm;
int lastAngle = -1;

void setup() {
  Serial.begin(115200);
  arm.attach(SERVO_PIN, 500, 2400);   // pulse width (us) for 0 and 180 degrees
  arm.write(90);                      // start in the middle
}

void loop() {
  int raw = analogRead(POT);              // 0..4095 on ESP32
  int angle = map(raw, 0, 4095, 0, 180);
  if (abs(angle - lastAngle) > 1) {       // ignore tiny ADC jitter
    arm.write(angle);
    lastAngle = angle;
    Serial.print("angle:");
    Serial.println(angle);
  }
  delay(20);
}

روش ۲: بدون کتابخانه، با ledc در ۵۰ هرتز

اگر می‌خواهی بفهمی پشت صحنه چه می‌گذرد، یا نمی‌خواهی کتابخانه نصب کنی، خودت پالس را با ledc بساز. ایده ساده است: یک کانال PWM با فرکانس ۵۰ هرتز و دقت ۱۶ بیت می‌سازیم. دوره‌ی هر موج ۲۰۰۰۰ میکروثانیه است و دقت ۱۶ بیتی یعنی این دوره به ۶۵۵۳۶ قسمت تقسیم می‌شود. پس برای پالس ۱۵۰۰ میکروثانیه‌ای، مقدار duty برابر ۱۵۰۰ ضرب در ۶۵۵۳۵ تقسیم بر ۲۰۰۰۰ است؛ یعنی حدود ۴۹۱۵.

// ESP32 servo without a library: ledc at 50 Hz (Arduino-ESP32 core 3.x).
const int SERVO_PIN = 18;
const int FREQ = 50;        // 50 pulses per second = 20 ms period
const int BITS = 16;        // duty range 0..65535

// convert a pulse width in microseconds to a 16-bit duty value
uint32_t usToDuty(int us) {
  uint32_t duty = us;       // 32-bit, so us * 65535 cannot overflow
  return duty * 65535 / 20000;
}

void writeAngle(int angle) {
  int us = map(angle, 0, 180, 500, 2400);
  ledcWrite(SERVO_PIN, usToDuty(us));
}

void setup() {
  ledcAttach(SERVO_PIN, FREQ, BITS);
}

void loop() {
  writeAngle(0);
  delay(1000);
  writeAngle(90);
  delay(1000);
  writeAngle(180);
  delay(1000);
}

این کد برای هسته‌ی نسخه‌ی ۳ نوشته شده است. اگر هسته‌ی نسخه‌ی ۲ داری، در setup بنویس ledcSetup(0, 50, 16); ledcAttachPin(SERVO_PIN, 0); و در writeAngle به‌جای پایه، شماره‌ی کانال را بده: ledcWrite(0, usToDuty(us)). فرق این دو نسخه را در آموزش PWM با ledc مفصل گفته‌ایم. برای حساب‌های duty و فرکانس هم ماشین‌حساب PWM به کار می‌آید.

تغذیه‌ی سروو: جایی که بیشتر پروژه‌ها خراب می‌شوند

سروو موقع شروع حرکت، مخصوصاً وقتی باری روی بازویش هست، در یک لحظه جریان زیادی می‌کشد: یک SG90 کوچک تا چند صد میلی‌آمپر و یک MG996R تا بیش از یک آمپر. اگر این جریان از همان USB بیاید که ESP32 را روشن نگه داشته، ولتاژ یک لحظه افت می‌کند و ESP32 با پیام Brownout detector was triggered در سریال مانیتور ریست می‌شود. این قانون‌ها را رعایت کن:

درباره‌ی انتخاب منبع تغذیه برای پروژه‌ها، راهنمای منبع تغذیه‌ی آردوینو نکته‌های خوبی دارد که برای ESP32 هم صادق است.

اجرا در شبیه‌ساز

در تینکرکد فارسی برد ESP32، سروو و پتانسیومتر را بگذار، سیم‌کشی جدول را انجام بده و کد روش ۱ (ESP32Servo) را اجرا کن. با چرخاندن ولوم، بازوی سروو هم‌زمان می‌چرخد و زاویه در سریال و نمودار دیده می‌شود. روش ۲ را روی برد واقعی امتحان کن. خواندن مثال‌ها رایگان است و اجرای ESP32 به اشتراک Plus نیاز دارد. همین مدار با آردوینو اونو به‌صورت رایگان در پروژه‌ی آماده‌ی پتانسیومتر کنترل سروو هست و درس «فرمان با ولوم» منطق map را قدم‌به‌قدم درس می‌دهد. اگر wokwi.com برایت کند باز می‌شود، این شبیه‌ساز روی اینترنت ملی هم کار می‌کند.

اشکال‌های رایج

نسخه‌ی آردوینوی همین آموزش را در سروو موتور با آردوینو و نسخه‌ی میکروپایتون را در سروو با پیکو ببین. قدم بعدی جذاب: سروو را از گوشی کنترل کن، با ترکیب همین کد و وب‌سرور ESP32. همه‌ی آموزش‌ها در صفحه‌ی ESP32.

سروو و پتانسیومتر را در تینکرکد فارسی بچرخان 🦾

سؤال‌های رایج

چرا کتابخانه‌ی Servo.h روی ESP32 کامپایل نمی‌شود؟

کتابخانه‌ی Servo که همراه آردوینو IDE است برای تایمرهای تراشه‌های AVR نوشته شده و ESP32 را نمی‌شناسد. به‌جایش کتابخانه‌ی ESP32Servo را از Library Manager نصب کن؛ دستورهایش تقریباً همان‌هاست.

سروو را به کدام پایه‌ی ESP32 وصل کنم؟

هر پایه‌ای که خروجی می‌شود و strapping نیست؛ مثلاً GPIO13، 18، 19، 23، 25، 26 یا 27. پایه‌های 34 تا 39 فقط ورودی‌اند و سروو را حرکت نمی‌دهند.

می‌شود سروو را از پایه‌ی 3V3 ESP32 تغذیه کرد؟

نه. سروو با ۵ ولت کار می‌کند و موقع حرکت جریان زیادی می‌کشد. یک SG90 را می‌شود از پایه‌ی VIN (۵ ولت USB) تغذیه کرد و سرووهای بزرگ‌تر منبع ۵ یا ۶ ولتی جدا با زمین مشترک می‌خواهند.

آیا سیگنال ۳٫۳ ولتی ESP32 برای سروو کافی است؟

برای بیشتر سرووهای رایج مثل SG90 و MG996R بله؛ آن‌ها پالس ۳٫۳ ولتی را به‌خوبی تشخیص می‌دهند. فقط زمین ESP32 و زمین تغذیه‌ی سروو باید به هم وصل باشند.

مقاله‌های مرتبط

📡

ESP32 در حالت Access Point: وب‌سرور بدون مودم با WiFi.softAP

😴

دیپ اسلیپ ESP32: خواب عمیق، بیدار شدن با تایمر و دکمه و ماه‌ها کار با یک باتری

🕰️

ساعت اینترنتی با ESP32: گرفتن ساعت دقیق از NTP به وقت تهران

🍓

اولین برنامه‌ی میکروپایتون روی رزبری پای پیکو: چشمک‌زن با machine.Pin

همه‌ی آموزش‌های ESP32 و اینترنت اشیا ← · همه‌ی مقاله‌ها