ورکشاپ آموزشی - آیسی مدار
رفتن به محتوا

گیم‌پد حرفه‌ای با میکروکنترلر STM32

ابزار و گجت
۰ نظر
۲۷ نفر
کد ۳۰۰۹

تا حالا به این فکر کردی که دسته بازی (گیم‌پد) خودت رو از صفر بسازی؟ دسته‌ای که هم با سیم کار کنه، هم بیسیم باشه و بتونی تمام کدهای داخلش رو به سلیقه خودت تغییر بدی؟ تو این آموزش از آیسی‌مدار، می‌خوایم یک کنترلر بازی خفن به اسم PIETROLLER بسازیم که قلب تپنده‌ش یک میکروکنترلر قدرتمند STM32 هست.

دلیل جذابیت این پروژه اینه که برخلاف دسته‌های بازی تجاری که کدهای بسته‌ای دارن و تعمیرشون سخته، این دسته کاملا متن‌باز (Open Source) طراحی شده. قطعاتش ارزون و در دسترسه، به راحتی تعمیر می‌شه و با پشتیبانی از پروتکل‌های X-INPUT و D-INPUT، می‌تونی هم بازی‌های قدیمی و هم بازی‌های روز رو باهاش تجربه کنی. برد بیسیمش هم به لطف ماژول NRF24L01 تا 100 متر جواب می‌ده و با مصرف انرژی خیلی پایین کار می‌کنه.

پس اگر دوست داری با دنیای میکروکنترلرهای ARM آشناتر بشی، مفاهیم USB HID رو یاد بگیری و یک گجت کاربردی برای خودت بسازی، هویه و قطعاتت رو آماده کن تا تو تیم آیسی‌مدار، قدم‌به‌قدم این گیم‌پد جذاب رو با هم بسازیم.

  1. کدهای کاملا قابل شخصی‌سازی (برخلاف سیستم‌های بسته تجاری)
  2. سخت‌افزار قابل تعمیر با قطعات ارزان و در دسترس
  3. کاهش زباله‌های الکترونیکی با تمرکز بر قابلیت تعمیرپذیری
  4. طراحی شده برای ساخت آسان و یادگیری همزمان مفاهیم
  5. کاملا متن‌باز (Open Source) به همراه تمام فایل‌های مورد نیاز
  6. تشویق به ایجاد تغییرات، آزمایش و ارتقا توسط جامعه کاربری
  7. تمرکز بر مالکیت واقعی، تعمیرپذیری و استفاده طولانی‌مدت
  1. پشتیبانی از چندین حالت کاری مختلف (X-INPUT / D-INPUT / بیسیم)
  2. استفاده از ماژول NRF24L01 برای ارسال و دریافت بسته‌های داده
  3. قابلیت ادغام آسان با سایر پروژه‌های رادیویی مبتنی بر NRF
  4. بسیار کم‌مصرف (متوسط 25 میلی‌آمپر و حتی کمتر در صورت خاموش بودن ال‌ای‌دی‌ها)
  5. پشتیبانی از بازی‌های قدیمی (D-INPUT) و بازی‌های جدید (X-INPUT)
  6. برد بیسیم تا 100 متر (قابل ارتقا تا 1 کیلومتر با استفاده از ماژول‌های آنتن‌دار NRF24L01 PA+LNA)

قطعات موردنیاز

  • میکروکنترلر STM32F103C8T6 (پکیج LQFP-48)
  • برد توسعه Blue Pill با تراشه STM32F103
  • پروگرامر ST-Link V2
  • 2 عدد ماژول فرستنده و گیرنده NRF24L01
  • آیسی مبدل CH340C (پکیج SOP-16)
  • 2 عدد ماژول جوی‌استیک
  • خازن الکترولیت 10 میکروفاراد
  • سوکت مادگی USB Type-B (اختیاری)
  • رگولاتور AP2138N-3.3 (پکیج SOT23-3)
  • آیسی محافظ USBLC6-4 (پکیج SOT23-6)
  • کریستال 8 مگاهرتز
  • فیوز برگشت‌پذیر (Polyfuse) 500 میلی‌آمپر
  • کانکتور نری USB-A
  • ال‌ای‌دی قرمز SMD سایز 0603
  • ال‌ای‌دی آبی SMD سایز 0603
  • پین هدر 1 در 4 با فاصله 2.54 میلی‌متر
  • 3 عدد مقاومت 10 کیلواهم
  • مقاومت 1 مگااهم
  • 2 عدد مقاومت 220 اهم
  • مقاومت 1.5 کیلواهم
  • 4 عدد مقاومت 1 کیلواهم
  • 6 عدد خازن 0.1 میکروفاراد (100 نانوفاراد)
  • 3 عدد خازن 1 میکروفاراد
  • خازن 10 میکروفاراد (SMD)
  • 3 عدد خازن 20 پیکوفاراد
  • خازن 10 نانوفاراد
  • نرم‌افزار STM32CubeIDE (نسخه 1.19.0 یا بالاتر برای تولید خودکار کدها)
  • نرم‌افزار STM32 Programmer (برای فلش کردن فریم‌ور روی آیسی)
  • نرم‌افزار ST-Link Utility (در صورتی که پروگرامر ST-Link شما کلون است)
مرحله ۱

چرا STM32؟ چرا از آردوینو استفاده نکردیم؟

  1. دلیل اصلی انتخاب STM32 به جای آردوینو، سرعت پردازش بالاتر، عملکرد بهتر و استفاده از معماری قدرتمند ARM هست. با اینکه آردوینو جامعه کاربری بزرگ و کتابخونه‌های آماده زیادی داره، اما هدف ما این بود که تو مفاهیم سیستم‌های نهفته (Embedded Systems) عمیق‌تر بشیم و همه‌چیز رو از پایه کنترل کنیم.
  2. کتابخونه‌های HID تو آردوینو کار رو خیلی ساده می‌کنن، اما انعطاف‌پذیری زیادی بهت نمی‌دن. در عوض با STM32 کنترل کامل و صددرصدی روی فریم‌ور (Firmware) دستگاهمون داریم.
  3. مورد بعدی دقت مبدل آنالوگ به دیجیتال (ADC) هست. میکروکنترلرهای سری F103 دارای ADC دوازده بیتی هستن (در برابر 10 بیتی آردوینو) که باعث می‌شه حرکات جوی‌استیک فوق‌العاده نرم و دقیق ثبت بشه.
  4. قیمت هم فاکتور خیلی مهمی بود. آیسی STM32 نسبت به پردازنده‌های اورجینال آردوینو بسیار ارزون‌تره و ارزش خرید بهتری برای یک محصول تولیدی داره.
  5. البته به لطف پروژه STM32Duino، تو همیشه این امکان رو داری که بردهای STM32 رو از طریق همون محیط آشنای Arduino IDE هم برنامه‌نویسی کنی.
  6. در یک کلام، STM32 تو این پروژه عملکرد بهتر، انعطاف بیشتر و قیمت پایین‌تری داره. البته می‌تونی ایده این دسته رو با آردوینو هم پیاده کنی، اما برای کاربرد ما، STM32 انتخاب منطقی‌تر و حرفه‌ای‌تری بود.
مرحله ۲

طراحی شماتیک و ساخت مدار چاپی (PCB)

اولین چالش تو هر پروژه الکترونیکی، طراحی بی‌نقص مداره تا بتونه برای مدت طولانی بدون مشکل کار کنه. همیشه یادت باشه که قبل از طراحی، دیتاشیت (Datasheet) قطعات رو با دقت بخونی. شرکت‌های سازنده معمولا تو دیتاشیت‌ها مدارات پایه‌ای (Minimum System) رو قرار می‌دن که نشون می‌ده برای راه‌اندازی قطعه دقیقا به چه خازن و مقاومت‌هایی نیاز داری. بیا بخش‌های مختلف مدارمون رو با هم بررسی کنیم:

  1. در بخش میکروکنترلر اصلی، 4 عدد خازن 0.1 میکروفاراد (100 نانوفاراد) می‌بینی. این‌ها خازن‌های دی‌کوپلینگ هستن که باید تا جای ممکن نزدیک به پایه‌های VDD و GND میکروکنترلر روی برد قرار بگیرن. اگر این خازن‌ها رو نذاری، میکروکنترلر بر اثر نویز و افت ولتاژهای لحظه‌ای ریست می‌شه.
  2. برای ارتباط USB، ما از خطوط D+ و D- استفاده کردیم که باید از طریق دو مقاومت سری 22 اهم به میکروکنترلر وصل بشن تا امپدانس خطوط تطبیق پیدا کنه. چون سرعت ارتباط ما در حد USB Full Speed (12 مگابیت بر ثانیه) هست، خیلی نیازی به روتینگ تفاضلی (Differential Routing) فوق‌حرفه‌ای روی برد نداریم و تغییرات جزئی مشکلی ایجاد نمی‌کنه.
  3. برای محافظت از پورت USB، یک آیسی USBLC6-4 قرار دادیم که نوسانات ناگهانی ولتاژ رو می‌گیره. همچنین یک فیوز برگشت‌پذیر 500 میلی‌آمپری هم گذاشتیم تا اگر اتصالی رخ داد، مدار نسوزه و بعد از رفع مشکل دوباره وصل بشه.
  4. برای انتخاب خازن‌های کریستال هم حتما به دیتاشیت سازنده توجه کن. البته اگر از رزوناتور استفاده کنی، اصلا نیازی به خازن خارجی نداری.

فرمول محاسبه خازن‌های کریستال اینه: Cl = (C1*C2)/(C1+C2) + Cstray. معمولا ظرفیت خازنی خود برد (Cstray) بین 2 تا 5 پیکوفاراد در نظر گرفته می‌شه. مثلا اگر دیتاشیت گفته ظرفیت کریستال 12 پیکوفاراده، ما باید دو تا خازن 20 پیکوفارادی در دو طرفش قرار بدیم.

  1. یک نکته خیلی مهم: حتما یک خازن الکترولیت 10 میکروفاراد بین پایه‌های تغذیه ماژول NRF24L01 قرار بده. این ماژول موقع ارسال داده تا 150 میلی‌آمپر جریان می‌کشه و اگر این خازن نباشه، به شدت دچار افت ولتاژ و قطع ارتباط می‌شه.
  2. تو این پروژه به جای رگولاتور معروف AMS1117 از آیسی AP2138 استفاده کردیم؛ چون جریان هدررفت (Quiescent Current) بسیار کمتری داره و برای پروژه‌هایی که با باتری کار می‌کنن، بازدهی عالی و پایداری بهتری میده.

وقتی شماتیک کامل شد، نوبت طراحی PCB هست. فایل‌های گربر (Gerber) برای این پروژه از قبل آماده شده و می‌تونی مستقیم اون‌ها رو برای چاپ استفاده کنی. فایل‌های مربوط به فرستنده و گیرنده هر دو برای ساخت در دسترس هستن.

طراحی این بردها پر از نکته‌های جالبه. من تو طراحی اول برد گیرنده، جای پایه‌های D+ و D- رو اشتباه زدم و دو هفته طول کشید تا بفهمم مشکل کجاست! جالب اینجاست که وسط امتحاناتم بود و به جای درس خوندن داشتم دیباگ می‌کردم. اما حالا تمام ایرادات برطرف شده و فایل‌هایی که در اختیارت قرار داره، کاملا تست شده و بدون نقصه.

مرحله ۳

مونتاژ قطعات و لحیم‌کاری برد

لحیم‌کاری قطعات SMD اون‌قدرها هم که به نظر می‌رسه ترسناک نیست. اگر از خمیر قلع و هیتر (دستگاه هوای گرم) استفاده می‌کنی، کار خیلی راحت‌تره. اما حتی با یک هویه معمولی هم می‌تونی این برد رو با کیفیت بالا مونتاژ کنی.

برای لحیم‌کاری دستی قطعات روی سطح، بهتره از یک هویه با قابلیت کنترل دما (مثل هویه‌های مدل T-12 یا Hakko با نوک 900M-T) استفاده کنی تا به قطعات ظریف آسیب نرسونی. اگر هویه‌ات دیمر نداره، حواست باشه که زیاد روشن نمونه، چون نوک هویه بیش از حد داغ می‌شه، اکسید می‌شه و لحیم‌کاری رو خراب می‌کنه.

یک قانون طلایی: همیشه بعد از اتمام کار، روی نوک هویه کمی قلع بزن تا تو استفاده بعدی خراب نشه. برای لحیم کردن قطعات دوپایه (مثل مقاومت‌ها و ال‌ای‌دی‌های سایز 0603 یا 0805) به این روش عمل کن: اول روی یکی از پدهای روی برد کمی قلع بذار.

  1. همون مقدار قلع رو با هویه آب کن و همزمان با پنس قطعه رو سر جاش قرار بده. وقتی یک سمت قطعه محکم شد، هویه رو بردار.
  2. حالا برو سراغ پد دوم و به راحتی لحیمش کن.
  3. اگر لحیم کدر شد یا خوب نچسبید، کمی روغن لحیم (Flux) بزن و دوباره گرمش کن تا براق و تمیز بشه.

برای لحیم‌کاری آیسی‌ها (پکیج‌های SOT-23، LQFP و SOP-16):

  1. مثل قطعات قبلی، اول فقط روی یک پد قلع بذار.
  2. آیسی رو سر جاش قرار بده (حتما به نقطه روی آیسی که نشون‌دهنده پایه شماره 1 هست دقت کن). آیسی رو تراز کن و اون یک پایه رو لحیم کن تا قطعه فیکس بشه.
  3. حالا روی بقیه پایه‌ها روغن لحیم بمال و روی همشون قلع بکش. اصلا نترس اگر پایه‌ها به هم اتصالی کردن! در آخر با استفاده از سیم قلع‌کش (Desoldering Braid) از جنس مس، به راحتی تمام قلع‌های اضافه رو جمع می‌کنی.
  4. در نهایت یک بار دیگه روغن لحیم بزن و با هویه تمیز پایه‌ها رو مرتب کن تا اتصال بی‌نقصی داشته باشی.

بعد از اینکه کل قطعات رو مونتاژ کردی، حتما برد رو با الکل ایزوپروپیل (IPA) با خلوص 99 درصد و یک مسواک تمیز کن تا تمام روغن لحیم‌ها پاک بشن و بردت مثل یک محصول کارخونه‌ای برق بزنه. فقط یادت باشه که الکل به شدت قابلیت اشتعال داره، پس مراقب باش.

مرحله ۴

تنظیمات نرم‌افزاری و برنامه‌نویسی میکروکنترلر

اینجا می‌رسیم به چالش دوم پروژه که مربوط به کدهای USB HID می‌شه. این همون بخشیه که ممکنه خیلی‌ها رو درگیر کنه، اما اگر مفاهیم پایه رو درک کنی، خیلی شیرینه.

وقتی یک دستگاه USB رو به کامپیوتر وصل می‌کنی، کامپیوتر وارد فرایندی به اسم Enumeration می‌شه؛ یعنی از دستگاه می‌پرسه "تو کی هستی و چه کارایی می‌تونی بکنی؟"

دستگاه هم در جواب اطلاعاتی مثل شناسه فروشنده (VID)، شناسه محصول (PID) و کلاس کاریش رو به کامپیوتر می‌ده. سیستم‌عامل با خوندن این اطلاعات می‌فهمه که با یک کیبورد، موس یا دسته بازی طرفه و درایور مناسبش رو لود می‌کنه.

تو این پروژه، STM32 خودش رو به عنوان یک USB HID (Human Interface Device) معرفی می‌کنه تا بدون نیاز به نصب هیچ درایور اضافی، مستقیما به عنوان یک گیم‌پد شناخته بشه. برای پیکربندی اولیه سخت‌افزار، ما از نرم‌افزار قدرتمند STM32CubeIDE استفاده کردیم. مراحل تنظیمات در STM32CubeIDE:

  1. ابتدا پوشه پروژه رو داخل IDE ایمپورت می‌کنی و فایل .IOC رو برای اعمال تنظیمات باز می‌کنی.
  2. تو بخش رابط کاربری (GUI)، پایه‌های ورودی و خروجی (GPIO)، پروتکل‌ها، کلاک (RCC) و مبدل‌های آنالوگ (ADC) رو تنظیم می‌کنی.
  3. همون‌طور که تو تصویر می‌بینی، با کلیک روی هر پایه می‌تونی ورودی یا خروجی بودنش رو مشخص کنی.
  4. برای ارتباطات، باید USB_FS و پروتکل SPI (برای ارتباط با ماژول NRF24L01) رو فعال کنی.
  5. سپس ADC رو فعال کرده و مشخص می‌کنی هر چند وقت یک‌بار نمونه‌برداری انجام بشه. با فعال کردن دسترسی مستقیم به حافظه (DMA)، داده‌ها بدون درگیر کردن پردازنده اصلی مستقیما تو متغیرها خونده می‌شن.

تنظیمات کلاک (Clock):

  1. مطابق با تصاویر، کلاک STM32 رو پیکربندی کن.
  2. قابلیتی تو نرم‌افزار هست که با توجه به پارامترهای خواسته شده، کلاک رو خودکار روی بهترین حالت تنظیم می‌کنه.
  3. برای کار با USB با سرعت کامل (FS)، میکروکنترلر به فرکانس دقیق 48 مگاهرتز نیاز داره. ما اینجا یک کریستال 12 مگاهرتز (HSE) داریم؛ پس از طریق واحد حلقه قفل فاز (PLL)، این فرکانس رو ضرب می‌کنیم تا به 48 مگاهرتز برسیم.
  4. همیشه تو رفرنس منوال‌ها چک کن که هر بخش محیطی (Peripheral) دقیقا از کدوم خط کلاک تغذیه می‌شه.

بیا نگاهی به چند بخش مهم کد بندازیم. تنظیمات شناسایی USB:

TXT
#define USBD_VID 1155 // logitech 0x46d
#define USBD_LANGID_STRING 1033
#define USBD_MANUFACTURER_STRING "Pie1722"
#define USBD_PID_FS 22322 // logitech 0xc218
#define USBD_PRODUCT_STRING_FS "PIETROLLER"
#define USBD_CONFIGURATION_STRING_FS "HID Config"
#define USBD_INTERFACE_STRING_FS "HID Interface"
  1. تو مسیر USB_DEVICE >> App فایل usbd_desc.c رو می‌تونی پیدا کنی. اینجا نام محصول و PID ثبت می‌شه.
  2. یادت باشه اگر نام دستگاه (Product String) رو تغییر دادی، حتما PID رو هم عوض کن؛ چون ویندوز نام دستگاه‌ها رو بر اساس PID کش (Cache) می‌کنه و اگر PID عوض نشه، همچنان همون نام قبلی رو بهت نشون می‌ده.
  3. من VID و PID دسته بازی شرکت لاجیتک (Logitech) رو به این کد دادم تا کامپیوتر اون رو به عنوان یک دسته بازی اورجینال و استاندارد بشناسه.

توصیف‌گرهای USB HID:

TXT
__ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END =
{
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x05, // Usage (Game Pad)
0xA1, 0x01, // Collection (Application)
// Buttons (12 x 1-bit)
0x05, 0x09, // Usage Page (Button)
0x19, 0x01, // Usage Minimum (Button 1)
0x29, 0x0C, // Usage Maximum (Button 12)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x95, 0x0C, // Report Count (12)
0x75, 0x01, // Report Size (1)
0x81, 0x02, // Input (Data,Var,Abs)
// Padding to byte-align after 12 buttons (4 bits)
0x95, 0x01, // Report Count (1)
0x75, 0x04, // Report Size (4)
0x81, 0x03, // Input (Const,Var,Abs) — Padding
// ---------------- 1 Hat Switch ----------------
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x39, // Usage (Hat switch)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x07, // Logical Maximum (7)
0x35, 0x00, // Physical Minimum (0)
0x46, 0x3B, 0x01, // Physical Maximum (315)
0x65, 0x14, // Unit (Eng Rot:Angular Pos)
0x75, 0x08, // Report Size (8)
0x95, 0x01, // Report Count (1)
0x81, 0x42, // Input (Data,Var,Abs,Null)
// Axes (X, Y, Zaxis, Z rotaion)
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x30, // Usage (X)
0x09, 0x31, // Usage (Y)
0x09, 0x32, // Usage (Zaxis)
0x09, 0x35, // Usage (Z rotaion)
0x16, 0x00, 0x80, // Logical Minimum (-32768)
0x26, 0xFF, 0x7F, // Logical Maximum (+32768)
0x75, 0x10, // Report Size (16)
0x95, 0x04, // Report Count (4)
0x81, 0x02, // Input (Data,Var,Abs)
0xC0 // End Collection
};
  1. این آرایه دقیقا به کامپیوتر می‌فهمونه که دستگاه ما یک گیم‌پد با چند دکمه و محور آنالوگ هست.
  2. این کدها رو می‌تونی تو مسیر Middleware >> ST >> STM32_USB_DEVICE_LIBRARY >> Class >> HID >> Src >> usbd_hid.c پیدا کنی.
  3. تا زمانی که تسلط کامل به استانداردهای USB نداری، این بخش رو تغییر نده.
  4. یک تغییر کوچیک می‌تونه باعث بشه ویندوز دیگه دسته بازی رو نشناسه.

میانگین‌گیری از ADC:

TXT
/** ADC ISR
* Handles the values from ADC after the conversion finished
*/
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
if ( adcValueReady == 0 ) {
x += adcVal[2];
y += adcVal[3];
lx += adcVal[0];
ly += adcVal[1];
count++;
}
// after 100 samples, average them
if (count >= 100) {
xRightStickValue_ADC = x / 100;
yRightStickValue_ADC = y / 100;
xLeftStickValue_ADC = lx / 100;
yLeftStickValue_ADC = ly / 100;
// reset for next round
x = 0;
y = 0;
lx = 0;
ly = 0;
count = 0;
adcValueReady = 1;
}
}
  1. میانگین‌گیری همون‌قدر که از اسمش پیداست ساده‌ست.
  2. از اونجایی که ADC میکروکنترلر ما ممکنه نویز داشته باشه، ما یک آرایه ساختیم که 100 تا نمونه آخر آنالوگ رو ذخیره می‌کنه.
  3. سپس مجموع این 100 داده رو بر 100 تقسیم می‌کنیم تا یک عدد نرم، بدون پرش و پایدار به دست بیاد.

تعریف نقطه کور (Deadzone) برای جوی‌استیک:

TXT
// ---- Axes: ADC static data ----
int16_t drx = xRightStickValue_ADC - xRightCenter;
int16_t dry = yRightStickValue_ADC - yRightCenter;
int16_t dlx = xLeftStickValue_ADC - xLeftCenter;
int16_t dly = yLeftStickValue_ADC - yLeftCenter;
// dead-zone (kill noise around center)
if (abs(drx) < 50) drx = 0;
if (abs(dry) < 50) dry = 0;
if (abs(dlx) < 50) dlx = 0;
if (abs(dly) < 50) dly = 0;
// end-zones (clip to safe ADC span)
if (drx > 2047) drx = 2047;
if (drx < -2047) drx = -2047;
if (dry > 2047) dry = 2047;
if (dry < -2047) dry = -2047;
if (dlx > 2047) dlx = 2047;
if (dlx < -2047) dlx = -2047;
if (dly > 2047) dly = 2047;
if (dly < -2047) dly = -2047;
report.x = (int16_t)map( drx, -2047, 2047, -32767, 32767);
report.y = (int16_t)map( dry, -2047, 2047, -32767, 32767);
report.zr = (int16_t)map( dlx, -2047, 2047, -32767, 32767);
report.za = (int16_t)map( dly, -2047, 2047, -32767, 32767);
adcValueReady = 0;
  1. این بخش مربوط به جبران ساییدگی و خطای جوی‌استیک‌هاست.
  2. نسخه اول فریم‌ور رو که نوشتم، برنامه‌ای برای نقطه کور نداشتم و بعد از مدتی جوی‌استیک شروع کرد به ارسال کدهای عجیب.
  3. جوی‌استیک‌ها در واقع مقاومت‌های متغیر (پتانسیومتر) هستن. بعد از چند ماه استفاده، فیلم کربنی داخلشون ساییده می‌شه و ممکنه وقتی دست بهشون نمی‌زنی، عدد صفر رو نشون ندن.
  4. برای حل این مشکل، ما یک "محدوده کور" یا Deadzone تعریف کردیم. یعنی تا زمانی که جوی‌استیک از یک محدوده مشخص خارج نشده، مقدارش صفر در نظر گرفته می‌شه.
  5. همین کار رو برای نقاط انتهایی (Endzones) هم انجام دادیم تا مقادیر همیشه تو یک بازه استاندارد باقی بمونن.
  6. این تکنیک دقیقا همون چیزیه که دسته‌های حرفه‌ای برای کالیبراسیون و افزایش طول عمر سنسورهاشون استفاده می‌کنن.
  7. من این روش رو از دسته بازی لاجیتک دوستم یاد گرفتم که با وجود 10 سال کار کردن، هنوز عالی جواب میده!
مرحله ۵

آپلود فریم‌ور (Firmware) روی STM32

برای فلش کردن برنامه‌ها روی آیسی، می‌تونی از نرم‌افزار STM32 ST-LINK Utility یا STM32Cube Programmer استفاده کنی. اگر آیسی میکروکنترلری که خریدی کلون (غیر اورجینال) باشه، ممکنه با Programmer ارور بده، پس بهتره از ST-LINK Utility استفاده کنی.

  1. پروگرامر ST-Link V2 رو به پایه‌های SWD برد STM32 وصل کن، نرم‌افزار رو باز کن و روی دکمه اتصال کلیک کن.
  2. وقتی وصل شد، اطلاعات و ظرفیت حافظه آیسی رو تو نرم‌افزار می‌بینی.

اگر می‌خوای دسته بازیت از همه حالت‌های D-INPUT، X-INPUT و بیسیم پشتیبانی کنه، اول از همه باید فریم‌ور Bootloader رو فلش کنی.

  1. فایل‌های با پسوند .hex رو از پوشه Debug هر پروژه پیدا کن.
  2. این فایل‌ها رو توی نرم‌افزار لود کن و روی میکروکنترلر پروگرم کن.

اما اگر فقط به یکی از حالت‌ها نیاز داری، باید وارد فایل‌های پروژه بشی، در فایل لینکر (STM32F103C8TX_FLASH.ld)، آدرس شروع حافظه رو به 0x08000000 تغییر بدی تا مستقیما اجرا بشه.

فایل‌های هگز (Hex) از پیش کامپایل شده در دسترس هستن و می‌تونی مستقیما و بدون هیچ دست‌کاری، اون‌ها رو روی آیسی آپلود کنی تا دستگاهت کار کنه. فایل‌های اصلی شامل: فریم‌ور بوت‌لودر، فریم‌ور حالت D-INPUT و فریم‌ور حالت X-INPUT هستن. برای بخش بیسیم هم یک فایل برای فرستنده و یک فایل برای دانگل گیرنده وجود داره.

مرحله ۶

تست نهایی دسته بازی و نحوه استفاده

حالا چطور باید از PIETROLLER استفاده کنیم؟

  1. بوت‌لودر: اگر دسته رو همین‌طوری به کامپیوتر وصل کنی، ممکنه سیستم ارور بده. باید دسته رو قطع کنی و با یکی از روش‌های زیر وصلش کنی.
  2. حالت D-INPUT: دکمه LB رو نگه دار و کابل USB رو به کامپیوتر وصل کن. اگر ال‌ای‌دی روی برد هر 500 میلی‌ثانیه چشمک زد، یعنی با موفقیت وارد این حالت شدی.
  3. حالت X-INPUT: دکمه LT رو نگه دار و کابل رو وصل کن. چشمک زدن سریع‌تر ال‌ای‌دی (هر 250 میلی‌ثانیه) نشون‌دهنده فعال شدن این حالته.
  4. حالت بیسیم: دکمه RT رو نگه دار و دسته رو با باتری یا هر پورت USB روشن کن. اگر دانگل گیرنده به کامپیوتر وصل باشه، ال‌ای‌دی دانگل روشن می‌شه که یعنی ارتباط بیسیم برقرار شده.

دیباگ و رفع ایراد:

  1. اگر می‌خوای ببینی مقادیر جوی‌استیک‌ها یا دکمه‌ها درست خونده می‌شه، پروگرامر رو وصل کن و در محیط STM32CubeIDE وارد حالت Live Debug بشو.
  2. اونجا می‌تونی مقادیر متغیرها و رجیسترها رو در لحظه ببینی، برنامه رو متوقف کنی (Breakpoint بذاری) و رفتار میکروکنترلر رو کاملا تحلیل کنی.

این دسته روی انواع بازی‌های قدیمی نوستالژیک تا جدیدترین بازی‌های روز تست شده و تا زمانی که مایکروسافت تصمیم نگیره استانداردهای درایورهاش رو کاملا تغییر بده، بدون هیچ مشکلی برات کار می‌کنه!

مرحله ۷

استفاده از این دسته برای کنترل ربات و پروژه‌های دیگه

یکی از جذاب‌ترین ویژگی‌های این پروژه اینه که به خاطر داشتن ماژول NRF24L01، می‌تونی ازش به عنوان یک ریموت کنترل حرفه‌ای برای هدایت پهپاد، ماشین کنترلی یا ربات‌های دست‌ساز خودت استفاده کنی. فقط کافیه یک برد آردوینو رو در نقش گیرنده به یک ماژول NRF وصل کنی. پین‌ها رو به این صورت ببند: 3.3 ولت ← VCC GND ← GND D10 ← CE (می‌تونی از پین‌های دیگه هم استفاده کنی و تو کد تغییرش بدی)

D9 ← CSN D13 ← SCK D11 ← MOSI D12 ← MISO فقط یادت باشه که تنظیمات رادیویی روی گیرنده آردوینو باید دقیقا با تنظیمات گیم‌پد STM32 یکی باشه.

TXT
byte rxAddr[5] = {0x45, 0x55, 0x67, 0x10, 0x21};

آدرس لوله ارتباطی (Address) باید کاملا مشابه باشه، وگرنه گیرنده هیچ بسته‌ای رو دریافت نمی‌کنه.

TXT
struct JoystickData {
uint16_t code;
uint16_t xAxis;
uint16_t yAxis;
uint16_t rXaxis;
uint16_t rYaxis;
uint16_t buttons; // 16 bits, 16 buttons
};
JoystickData joy;

ساختار داده (Data Structure) هم باید مطابق با فرستنده باشه تا وقتی داده‌ها رسیدن، آردوینو بتونه به درستی رمزگشایی‌شون کنه.

TXT
// These config below should be the same to receiver packets from PIETROLLER
radio.setPALevel(RF24_PA_MAX);
radio.setDataRate(RF24_2MBPS);
radio.setChannel(76); // set the same channel
radio.setPayloadSize(PLD_S);
radio.setAddressWidth(5);
radio.setAutoAck(true);
radio.disableAckPayload();
radio.disableDynamicPayloads();
//radio.enableDynamicPayloads();
radio.setCRCLength(RF24_CRC_16);
//radio.disableCRC();
radio.openReadingPipe(0, rxAddr);
radio.startListening();

توان فرستنده (PA Level) رو می‌تونی بسته به نیازت تنظیم کنی. روی حالت حداکثر (0dbm) بالاترین برد رو داری، اما حواست باشه که تا 150 میلی‌آمپر جریان می‌کشه. با کدهای آماده‌ای که وجود داره، تبدیل این دسته به یک ریموت رباتیک مثل آب خوردنه!

مرحله ۸

سخن پایانی و توسعه پروژه

خب، اینم از آموزش ساخت کنترلر PIETROLLER! ساخت این گیم‌پد یک تجربه عالی برای یادگیری کار با میکروکنترلرهای STM32 و مفاهیم پیچیده‌ای مثل USB HID و ارتباطات رادیویی بود. از اونجایی که این پروژه کاملا متن‌بازه، خیلی جای پیشرفت و ارتقا داره و تو می‌تونی اون رو به سطح بالاتری ببری.

  1. می‌تونی کدهای این پروژه رو بررسی کنی و تغییرات شخصی‌سازی شده خودت رو اعمال کنی.
  2. اضافه کردن موتور ویبره (Haptic feedback) می‌تونه یک ایده فوق‌العاده برای قدم بعدی باشه. یک تابع نیمه‌کاره برای این مورد تو کتابخونه وجود داره که می‌تونی تکمیلش کنی.
  3. طراحی یک قاب سه‌بعدی جذاب و ارگونومیک هم ارزش این پروژه رو چند برابر می‌کنه.

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

فایل‌های پیوست

HEX blue pill bootloader.hex
HEX blue pill dinput.hex
HEX blue pill xinput.hex

تو میتونی اولین سازنده باشی!

اگه پروژه رو ساختی به اشتراک بزار و اعتبار هدیه بگیر

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

آموزش‌های مشابه

گفتگو‌های کاربران

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