ساخت ربات تعاملی با Arduino Nano و OLED؛ آموزش کامل ربات هوشمند با سنسور لمسی
ساخت ربات تعاملی با Arduino Nano و نمایشگر OLED:
در این پروژه یک ربات تعاملی با استفاده از Arduino Nano، نمایشگر OLED و سنسور لمسی میسازیم. چهره ربات روی نمایشگر OLED بهصورت گرافیکی طراحی شده و با توجه به شرایط مختلف تغییر میکند.
ربات در حالت عادی به جهات مختلف نگاه میکند، با لمس کوتاه خوشحال میشود، با لمس طولانی عصبانی میشود و در صورت عدم دریافت ورودی برای مدت مشخص، حالت بیحوصلگی پیدا میکند.
این پروژه برای آشنایی با Arduino، ارتباط I2C، نمایش گرافیکی روی OLED، دریافت ورودی دیجیتال، کنترل زمان و طراحی حالتهای مختلف یک رابط گرافیکی مناسب است.
🧰 قطعات مورد نیاز
برای ساخت این پروژه به قطعات زیر نیاز دارید:
| Arduino Nano یا Arduino UNO | ۱ |
| OLED 1.3 Inch SH1106 128×64 | ۱ |
| ماژول سنسور لمسی | ۱ |
| سیم جامپر | چند عدد |
| بردبورد | ۱ |
| کابل USB آردوینو | ۱ |
🎯 امکانات ربات
ربات ساختهشده در این پروژه دارای رفتارهای زیر است:
👀 نگاه کردن به اطراف
در حالت عادی، چشمهای ربات هر یک ثانیه یک جهت را بهصورت تصادفی انتخاب میکنند:
- مستقیم
- چپ
- راست
- بالا
- پایین
مردمکها برای هر جهت جابهجا میشوند و ظاهر صورت نیز در کنار حرکت چشمها نمایش داده میشود.
😊 لمس کوتاه
با یک لمس کوتاه، ربات بهآرامی خوشحال میشود.
تغییرات چهره شامل:
- نیمهباز شدن چشمها
- بالا رفتن ابروها
- ایجاد لبخند
- باقی ماندن در حالت خوشحال به مدت ۲ ثانیه
- بازگشت آرام به حالت عادی
است.
😠 لمس طولانی
با نگه داشتن انگشت روی سنسور لمسی برای بیشتر از ۱.۵ ثانیه، ربات بهآرامی عصبانی میشود.
تغییرات چهره شامل:
- تغییر ابروها
- باریک شدن چشمها
- تغییر حالت دهان
- افزایش تدریجی شدت حالت عصبانیت
- باقی ماندن در حالت عصبانی به مدت ۲ ثانیه
- بازگشت تدریجی به حالت عادی
است.
😴 بیحوصلگی
در صورتی که برای مدتی با ربات تعامل نشود، حالت چهره بهتدریج تغییر میکند.
چشمها به سمت بالا میروند، پلکها پایین میآیند، ابروها حالت خستگی پیدا میکنند و دهان نیز حالت بیحوصلگی میگیرد.
بردبورد برای اجرای آزمایشی پروژه استفاده میشود و در نسخه نهایی مدار میتوان قطعات را به روش مناسب دیگری متصل کرد.
🖥️ نمایشگر مورد استفاده
نمایشگر این پروژه:
OLED 1.3 Inch با درایور SH1106
است.
مشخصات نمایشگر:
| نوع | OLED |
| اندازه | 1.3 اینچ |
| رزولوشن | 128×64 |
| رابط | I2C |
| درایور | SH1106 |
| آدرس I2C پروژه | 0x3C |
نمایشگر از طریق ارتباط I2C با Arduino ارتباط برقرار میکند.
در این پروژه از کتابخانه Adafruit_SH110X برای کنترل نمایشگر استفاده شده است.
📚 کتابخانههای مورد نیاز
برای اجرای کد پروژه سه کتابخانه مورد نیاز است:
Wire
Adafruit GFX
Adafruit SH110X
1. کتابخانه Wire
کتابخانه Wire برای ارتباط I2C استفاده میشود.
این کتابخانه در Arduino IDE بهصورت پیشفرض وجود دارد و نیازی به نصب جداگانه ندارد.
در ابتدای کد با دستور زیر فراخوانی میشود:
#include <Wire.h>
2. کتابخانه Adafruit GFX
این کتابخانه امکانات گرافیکی مورد استفاده پروژه را فراهم میکند.
در این پروژه برای رسم موارد زیر استفاده شده است:
- دایره
- خط
- مستطیل
- مستطیل گوشهگرد
- اشکال مربوط به چشم
- مردمک
- ابرو
- دهان
کتابخانه با دستور زیر در برنامه فراخوانی میشود:
#include <Adafruit_GFX.h>
3. کتابخانه Adafruit SH110X
این کتابخانه برای کنترل نمایشگرهای OLED مبتنی بر درایور SH1106 استفاده میشود.
در این پروژه نمایشگر با کلاس زیر تعریف شده است:
Adafruit_SH1106G display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
و کتابخانه با دستور زیر فراخوانی میشود:
#include <Adafruit_SH110X.h>
📥 نصب کتابخانهها
در Arduino IDE از مسیر زیر وارد Library Manager شوید:
Sketch ↓ Include Library ↓ Manage Libraries
در قسمت جستجو عبارت زیر را وارد کنید:
Adafruit GFX
کتابخانه Adafruit GFX Library را نصب کنید.
سپس عبارت زیر را جستجو کنید:
Adafruit SH110X
کتابخانه Adafruit SH110X را نصب کنید.
کتابخانه Wire از قبل همراه Arduino IDE قرار دارد.
🔌 اتصالات مدار
اتصال OLED به Arduino UNO به شکل زیر است:
پایه OLEDپایه Arduino UNO
| VCC | 5V |
| GND | GND |
| SDA | A4 |
| SCL | A5 |
اتصال I2C در Arduino UNO
در Arduino UNO پایههای ارتباط I2C عبارتاند از:
A4 = SDA A5 = SCL
بنابراین اتصال نمایشگر باید دقیقاً به شکل زیر باشد:
OLED SDA → Arduino A4 OLED SCL → Arduino A5
پایههای A4 و A5 در این پروژه برای ارتباط I2C استفاده میشوند.
👆 اتصال سنسور لمسی
سنسور لمسی مورد استفاده دارای سه اتصال اصلی است:
VCC GND OUT
اتصال آن:
سنسور لمسیArduino UNO
| VCC | 5V |
| GND | GND |
| OUT | D2 |
بنابراین پایه OUT سنسور به پایه دیجیتال شماره ۲ متصل میشود.
در برنامه نیز این پایه با دستور زیر مشخص شده است:
#define TOUCH_PIN 2
و در setup() بهعنوان ورودی تعریف میشود:
pinMode(TOUCH_PIN, INPUT);
اتصالات کامل پروژه:
Arduino UNO ┌───────────────┐ │ │ OLED SDA ────┤ A4 │ OLED SCL ────┤ A5 │ │ │ Touch OUT ────┤ D2 │ │ │ OLED VCC ────┤ 5V │ Touch VCC ────┤ 5V │ │ │ OLED GND ────┤ GND │ Touch GND ────┤ GND │ └───────────────┘
تمام قطعات مدار باید زمین مشترک داشته باشند.
یعنی:
OLED GND │ ├──── Arduino GND │ Touch GND
⚠️ نکته مهم درباره OLED
در این پروژه نمایشگر با آدرس I2C زیر استفاده شده است:
0x3C
در صورتی که نمایشگر شما توسط I2C Scanner با عبارت زیر شناسایی شود:
Found: 0x3C
آدرس صحیح برای این پروژه را دارید.
کد مربوط به راهاندازی نمایشگر نیز به همین آدرس اشاره میکند:
display.begin(0x3C, true)
برای دانلود فایل آردوینو پروژه رو گزینه زیر کلیک کنید
🔎 تشخیص مشکل نمایشگر
در صورتی که OLED روشن نشد، ابتدا سیمهای I2C را بررسی کنید:
SDA → A4 SCL → A5
سپس تغذیه را بررسی کنید:
VCC → 5V GND → GND
برای بررسی ارتباط I2C میتوانید از برنامه I2C Scanner استفاده کنید.
خروجی صحیح برای این پروژه:
Found: 0x3C
است.
وجود 0x3C نشان میدهد Arduino توانسته است دستگاه I2C را شناسایی کند.
🧠 ساختار نرمافزار پروژه
برنامه به چند بخش اصلی تقسیم شده است:
راهاندازی OLED ↓ نمایش حالت عادی ↓ حرکت تصادفی چشمها ↓ بررسی سنسور لمسی ↓ ┌───────────────┐ │ │ لمس کوتاه لمس طولانی │ │ ↓ ↓ خوشحال عصبانی │ │ ↓ ↓ بازگشت بازگشت │ │ └───────┬───────┘ ↓ حالت عادی ↓ عدم تعامل ↓ بیحوصلگی
ساختار برنامه و نحوه عملکرد ربات
در بخش قبل قطعات مورد نیاز، کتابخانهها و اتصالات پروژه را بررسی کردیم. در این بخش وارد قسمت نرمافزاری پروژه میشویم و میبینیم برنامه چگونه چهره ربات را کنترل میکند.
هدف برنامه فقط نمایش یک تصویر ثابت روی OLED نیست. چهره ربات بهصورت زنده توسط Arduino رسم میشود و هر قسمت از صورت میتواند مستقل از قسمتهای دیگر تغییر کند.
ساختار کلی برنامه
برنامه از چند بخش اصلی تشکیل شده است:
بخش وظیفه
| راهاندازی OLED | برقراری ارتباط Arduino با نمایشگر |
| حالت عادی | نمایش چهره معمولی ربات |
| حرکت چشمها | تغییر جهت نگاه ربات |
| حالت خوشحالی | واکنش به لمس کوتاه |
| حالت عصبانیت | واکنش به لمس طولانی |
| حالت بیحوصلگی | واکنش به عدم تعامل برای مدت مشخص |
| کنترل سنسور | تشخیص شروع و پایان لمس |
| کنترل زمان | اندازهگیری مدت لمس و زمان بیتعامل بودن |
برنامه با راهاندازی OLED شروع میشود. پس از برقراری ارتباط، چهره اولیه ربات روی نمایشگر قرار میگیرد.
بعد از آن Arduino وارد حلقه اصلی برنامه میشود و بهصورت مداوم دو مورد را بررسی میکند؛ وضعیت سنسور لمسی و زمان سپریشده از آخرین تعامل با ربات.
ایجاد نمایشگر در برنامه
برای کنترل OLED ابتدا ابعاد نمایشگر مشخص میشود. نمایشگر این پروژه دارای عرض ۱۲۸ پیکسل و ارتفاع ۶۴ پیکسل است.
در برنامه این ابعاد با استفاده از دو متغیر مشخص شدهاند:
#define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64
سپس نمایشگر با استفاده از کتابخانه Adafruit SH110X تعریف میشود:
Adafruit_SH1106G display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
در این قسمت Arduino متوجه میشود که قرار است با یک نمایشگر SH1106 با رزولوشن ۱۲۸ در ۶۴ پیکسل و از طریق رابط I2C کار کند.
تعریف پایه سنسور لمسی
پایه خروجی سنسور لمسی به D2 متصل شده است.
برای اینکه در تمام قسمتهای برنامه بهجای نوشتن عدد ۲ بتوانیم از یک نام مشخص استفاده کنیم، در ابتدای برنامه پایه را با نام TOUCH_PIN تعریف کردهایم.
#define TOUCH_PIN 2
این کار باعث میشود در صورت تغییر پایه سنسور در آینده، فقط یک قسمت از برنامه نیاز به تغییر داشته باشد.
راهاندازی OLED
در قسمت setup ابتدا پایه سنسور بهعنوان ورودی تنظیم میشود:
pinMode(TOUCH_PIN, INPUT);
سپس OLED با آدرس I2C برابر با 0x3C راهاندازی میشود:
display.begin(0x3C, true);
در صورتی که نمایشگر بهدرستی شناسایی نشود، برنامه در همان مرحله متوقف میشود.
بعد از راهاندازی نمایشگر، صفحه پاک میشود تا اطلاعات قبلی روی آن باقی نماند.
ساخت چهره ربات
یکی از قسمتهای مهم این پروژه، طراحی چهره با اشکال گرافیکی ساده است.
OLED مورد استفاده در پروژه دارای ۱۲۸ در ۶۴ پیکسل است. هر پیکسل میتواند روشن یا خاموش باشد. بنابراین میتوان با روشن کردن مجموعهای از پیکسلها، چشم، ابرو و دهان ساخت.
برای چشمها از مستطیلهای گوشهگرد استفاده شده است.
برای مردمکها از دایره استفاده شده است.
برای ابروها از خط استفاده شده است.
دهان نیز با چند خط ساده ساخته شده است.
به همین روش میتوان چهرههای مختلفی ایجاد کرد بدون اینکه نیاز به تصویر یا فایل گرافیکی جداگانه داشته باشیم.
حرکت چشمها
برای اینکه ربات در حالت عادی به اطراف نگاه کند، چند حالت مختلف برای جهت نگاه تعریف شده است.
در حالت نگاه به چپ، مردمکهای هر دو چشم به سمت چپ منتقل میشوند.
در حالت نگاه به راست، مردمکها به سمت راست منتقل میشوند.
در حالت نگاه به بالا، مردمکها به سمت بالای چشمها منتقل میشوند.
در حالت نگاه به پایین، مردمکها به سمت پایین منتقل میشوند.
در حالت نگاه مستقیم، مردمکها تقریباً در مرکز چشم قرار میگیرند.
این کار با تغییر مختصات X و Y مردمک انجام میشود.
بهعنوان مثال، وقتی مقدار X منفی باشد، مردمک به سمت چپ حرکت میکند و وقتی مقدار X مثبت باشد، مردمک به سمت راست حرکت میکند.
برای حرکت عمودی نیز مقدار Y تغییر میکند.
انتخاب تصادفی جهت نگاه
برای طبیعیتر شدن رفتار ربات، جهت نگاه بهصورت تصادفی انتخاب میشود.
برنامه با استفاده از تابع random یک عدد تصادفی تولید میکند و بر اساس عدد تولیدشده یکی از پنج جهت را انتخاب میکند.
پنج حالت عبارتاند از:
شماره جهت نگاه
| ۰ | چپ |
| ۱ | راست |
| ۲ | بالا |
| ۳ | پایین |
| ۴ | مستقیم |
به این ترتیب ربات در هر بار تغییر نگاه، الزاماً به یک جهت مشخص نمیرود.
برای تولید عددهای تصادفی بهتر نیز در ابتدای برنامه از مقدار خواندهشده از ورودی آنالوگ A0 بهعنوان Seed استفاده شده است.
چرا از delay زیاد استفاده نشده است؟
یکی از نکات مهم در طراحی این پروژه، کنترل زمان با millis است.
در برنامه اصلی، Arduino باید همزمان چند کار را انجام دهد. باید وضعیت سنسور را بررسی کند، مدت لمس را اندازه بگیرد، زمان بیتعامل بودن را محاسبه کند و جهت نگاه را تغییر دهد.
استفاده زیاد از delay باعث میشود Arduino برای مدت مشخصی متوقف شود و در این مدت نتواند ورودی سنسور را بهدرستی بررسی کند.
به همین دلیل برای کنترل زمانهای اصلی برنامه از تابع millis استفاده شده است.
تابع millis مدت زمان سپریشده از شروع اجرای برنامه را بر حسب میلیثانیه در اختیار برنامه قرار میدهد.
این روش باعث میشود کنترل رفتار ربات دقیقتر و روانتر انجام شود.
تشخیص لمس کوتاه و طولانی
یکی از قسمتهای مهم پروژه تشخیص مدت زمان لمس است.
Arduino فقط بررسی نمیکند که سنسور لمس شده یا نشده است. زمان شروع لمس نیز ذخیره میشود.
وقتی سنسور از حالت بدون لمس به حالت لمس میرود، زمان شروع لمس در یک متغیر ذخیره میشود.
سپس تا زمانی که انگشت روی سنسور قرار دارد، برنامه مدت زمان گذشته را محاسبه میکند.
در صورتی که مدت لمس کمتر از ۱.۵ ثانیه باشد، لمس کوتاه در نظر گرفته میشود.
در صورتی که مدت لمس به ۱.۵ ثانیه برسد، برنامه وارد حالت عصبانیت میشود.
این منطق باعث میشود یک سنسور لمسی ساده بتواند دو نوع فرمان مختلف برای ربات ایجاد کند.
واکنش به لمس کوتاه
هنگامی که کاربر سنسور را برای مدت کوتاهی لمس میکند، برنامه وارد حالت خوشحالی میشود.
این حالت در چند مرحله طراحی شده است تا تغییر چهره ناگهانی نباشد.
ابتدا حالت اول خوشحالی نمایش داده میشود. در این مرحله تغییرات چهره کم هستند.
سپس حالت دوم نمایش داده میشود و چشمها، ابروها و دهان بیشتر تغییر میکنند.
در مرحله آخر، ربات به حالت خوشحالی کامل میرسد.
این روش باعث میشود حرکت چهره شبیه یک انیمیشن کوتاه به نظر برسد.
بعد از رسیدن به حالت نهایی، ربات حدود دو ثانیه در حالت خوشحال باقی میماند.
سپس همین مراحل بهصورت معکوس اجرا میشوند تا ربات بهآرامی به حالت عادی بازگردد.
واکنش به لمس طولانی
برای لمس طولانی نیز یک انیمیشن چندمرحلهای طراحی شده است.
در مرحله اول تغییرات بسیار کم هستند.
در مرحله دوم ابروها بیشتر به حالت خشمگین تغییر میکنند و چشمها کمی باریکتر میشوند.
در مرحله سوم حالت عصبانیت شدیدتر میشود.
در مرحله چهارم ربات به حالت خشمگین کامل میرسد.
پس از حدود دو ثانیه، برنامه مراحل برگشت را اجرا میکند و ربات از حالت خشمگین به حالت عادی بازمیگردد.
این روش باعث میشود تغییر چهره بهصورت تدریجی انجام شود و ربات حالت طبیعیتری داشته باشد.
حالت بیحوصلگی
برای اینکه ربات فقط هنگام لمس واکنش نشان ندهد، یک تایمر جداگانه برای آخرین تعامل کاربر در نظر گرفته شده است.
هر بار که کاربر با ربات تعامل میکند، زمان آخرین تعامل ذخیره میشود.
اگر برای مدت مشخصی هیچ تعاملی انجام نشود، برنامه متوجه میشود که ربات مدت زیادی بدون استفاده مانده است.
در این مرحله ربات وارد حالت بیحوصلگی میشود.
در ابتدا چشمها و ابروها کمی تغییر میکنند.
سپس چشمها به سمت بالا حرکت میکنند و حالت خستگی بیشتری ایجاد میشود.
در حالت نهایی، چشمها تقریباً نیمهباز هستند و مردمکها به سمت بالا قرار میگیرند.
این تغییرات باعث میشوند چهره ربات حس بیحوصلگی و انتظار را منتقل کند.
تغییر حالت دهان و ابرو
در این پروژه دهان و ابروها صرفاً عناصر تزئینی نیستند.
برای هر حالت چهره، موقعیت و شکل آنها تغییر میکند.
در حالت عادی، ابروها تقریباً صاف هستند و دهان حالت طبیعی دارد.
در حالت خوشحالی، ابروها کمی بالاتر قرار میگیرند و دهان به شکل لبخند درمیآید.
در حالت عصبانیت، ابروها به سمت داخل و پایین متمایل میشوند و دهان حالت اخم پیدا میکند.
در حالت بیحوصلگی، ابروها و دهان حالت خستهتری پیدا میکنند.
به همین دلیل حتی با وجود اینکه نمایشگر فقط ۱۲۸ در ۶۴ پیکسل است، میتوان حالتهای مختلف احساسی را با چند شکل ساده ایجاد کرد.
فایل پروژه
برای راحتی کاربران، فایل کامل پروژه را میتوان در انتهای همین آموزش قرار داد.
فایل اصلی پروژه شامل کد کامل Arduino است.
دیدگاه خود را بنویسید