اجرای LLM روی ESP32، آموزش کامل راهاندازی esp32-ai
آیا میتوان یک مدل زبانی یا LLM را بدون اینترنت و بدون سرور روی یک میکروکنترلر اجرا کرد؟ پروژه متنباز esp32-ai نشان میدهد پاسخ این سؤال مثبت است؛ البته نه روی هر مدل ESP32. در این پروژه یک مدل زبانی ۲۸٫۹ میلیون پارامتری روی برد ESP32-S3 اجرا میشود، متن را روی خود تراشه تولید میکند و هیچ اطلاعاتی را به API یا سرور خارجی نمیفرستد.
در این آموزش آرمین کیت، ابتدا مشخص میکنیم چه بردی لازم است، سپس ابزارها را نصب میکنیم، مدل Barista یا TinyStories را دریافت و فلش میکنیم، خروجی را در Serial Monitor میبینیم و در صورت نیاز نمایشگر OLED را نیز متصل میکنیم.
هشدار مهم برای ESP32-WROOM-32: اگر برد شما ESP32-WROOM-32 معمولی است، نسخه آماده این پروژه روی آن اجرا نمیشود. این برد معمولاً ۴ مگابایت Flash دارد و فاقد PSRAM روی ماژول است؛ درحالیکه پروژه به ESP32-S3 با ۱۶ مگابایت Flash و ۸ مگابایت PSRAM نیاز دارد.
esp32-ai چیست؟
مخزن slvDev/esp32-ai یک پیادهسازی پژوهشی و متنباز برای اجرای مدل زبانی کوچک روی میکروکنترلر ESP32-S3 است. مدل اصلی آن ۲۸٫۹ میلیون پارامتر دارد، با دقت ۴ بیتی ذخیره شده و اندازه فایل آن حدود ۱۴٫۹ مگابایت است.
برخلاف پروژههایی که ESP32 را فقط به ChatGPT یا یک API اینترنتی متصل میکنند، در این پروژه:
- وزنهای مدل داخل Flash برد ذخیره میشوند.
- محاسبات استنتاج روی خود ESP32-S3 انجام میشود.
- مدل برای تولید متن به Wi-Fi، اینترنت یا سرور نیاز ندارد.
- خروجی از USB Serial و در صورت تمایل از OLED نمایش داده میشود.
- سرعت اعلامشده برای TinyStories حدود ۹٫۸۸ توکن در ثانیه است.
این مدل جایگزین ChatGPT نیست. TinyStories فقط داستانهای کوتاه و ساده انگلیسی تولید میکند و Barista برای پرسشوپاسخ محدود درباره اسپرسو آموزش دیده است. ارزش اصلی پروژه، نمایش یک معماری هوشمند برای جا دادن مدل در حافظه بسیار محدود میکروکنترلر است.
آیا پروژه روی ESP32-WROOM-32 اجرا میشود؟
خیر؛ فریمور آماده و مدلهای منتشرشده برای ESP32-WROOM-32 مناسب نیستند.

| مشخصه | ESP32-WROOM-32 معمولی | ESP32-S3 N16R8 موردنیاز |
|---|---|---|
| معماری پردازنده | ESP32 / Xtensa LX6 | ESP32-S3 / Xtensa LX7 |
| Flash روی ماژول | معمولاً 4MB | 16MB |
| PSRAM روی ماژول | ندارد | 8MB OPI |
| فایل TinyStories | حدود 14.9MB | در Flash جا میشود |
| تنظیم پروژه | esp32 |
esp32s3 |
| نتیجه | ناسازگار | سازگار |
فایل TinyStories بهتنهایی ۱۴٬۹۱۲٬۳۴۸ بایت است. علاوه بر فضای Flash، هسته مدل و خروجی آن هنگام اجرا چند مگابایت PSRAM مصرف میکنند. اسکریپت رسمی پروژه نیز برد را صریحاً با FlashSize=16M و PSRAM=opi کامپایل میکند.
بنابراین برد پیشنهادی ما این است:
ESP32-S3-DevKitC-1 با ماژول ESP32-S3-WROOM-1-N16R8
هنگام خرید فقط به عبارت «ESP32-S3» اکتفا نکنید. کد N16R8 مهم است:
N16یعنی ۱۶ مگابایت FlashR8یعنی ۸ مگابایت PSRAM
نسخه N8، نسخه بدون PSRAM یا مدلهای R2 برای اجرای آماده این پروژه انتخاب مطمئنی نیستند.
مدل چگونه در حافظه ESP32-S3 جا میشود؟

این پروژه تمام مدل را داخل RAM کپی نمیکند. دادهها بر اساس تعداد دفعات دسترسی میان سه سطح حافظه تقسیم میشوند:
- SRAM سریع و کوچک: فعالسازیها و وزنهای نرمالسازی که در هر توکن بارها استفاده میشوند.
- PSRAM متوسط: هسته متراکم مدل و سر خروجی که در هر موقعیت خوانده میشوند.
- Flash بزرگتر و کندتر: جدول بزرگ embedding که بیشتر پارامترها در آن قرار دارند.
پروژه از ایده Per-Layer Embeddings استفاده میکند. حدود ۲۵ میلیون پارامتر داخل یک جدول Flash باقی میماند و در هر توکن فقط چند ردیف موردنیاز خوانده میشود. به این ترتیب لازم نیست تمام مدل همزمان در RAM حضور داشته باشد.
مدلهای آماده پروژه
مدل Barista
برای اولین آزمایش، Barista انتخاب مناسبتری است؛ زیرا میتوان سؤال را در Serial Monitor تایپ کرد و پاسخ را دید.
- ۸٫۹ میلیون پارامتر
- فایل وزن تقریباً ۴٫۶ مگابایت
- واژگان ورودی ۸٬۰۵۷ توکن
- ۸۵۴ کلاس خروجی
- آموزشدیده برای سؤالهای انگلیسی درباره اسپرسو
- پشتیبانی از Serial و OLED اختیاری
مدل TinyStories
- ۲۸٫۹ میلیون پارامتر
- مدل ۴ بیتی با حجم حدود ۱۴٫۹ مگابایت
- تولید داستانهای کوتاه انگلیسی
- سرعت اعلامشده حدود ۹٫۸۸ توکن بر ثانیه
- توانایی محدود؛ مناسب سؤال عمومی، کدنویسی یا مکالمه فارسی نیست
برد فقط یک پارتیشن مدل دارد. هر بار که مدل دیگری را Deploy میکنید، مدل قبلی جایگزین میشود.
قطعات و ابزارهای موردنیاز
سختافزار
- برد ESP32-S3 N16R8
- کابل USB دادهدار و سالم
- رایانه با Linux یا macOS؛ یا Windows 11 به همراه WSL2
- نمایشگر OLED تکرنگ 128×64 با رابط I2C، اختیاری
- چهار سیم جامپر مادگی به مادگی، در صورت استفاده از OLED
نرمافزار
- Git
- Python 3
- کامپایلر C/C++ شامل
ccوc++ - Arduino CLI
- هسته Arduino برای ESP32
- ابزار
uv - ابزار
hfاز بستهhuggingface_hub esptool؛ معمولاً همراه هسته ESP32 نصب میشود

روش پیشنهادی در ویندوز: Ubuntu روی WSL2
اسکریپتهای پروژه Bash هستند. مسیر مطمئن در ویندوز استفاده از Ubuntu در WSL2 است.
PowerShell را با دسترسی Administrator باز کنید:
wsl --install -d Ubuntu
wsl --update
پس از راهاندازی مجدد، Ubuntu را اجرا و نام کاربری و رمز لینوکس را ایجاد کنید.
متصل کردن USB برد به WSL2
ویندوز USB را بهصورت خودکار داخل WSL در اختیار Ubuntu نمیگذارد. ابزار رسمی پیشنهادی usbipd-win است.
در PowerShell مدیر:
winget install --interactive --exact dorssel.usbipd-win
usbipd list
برد را در فهرست پیدا و BUSID آن را یادداشت کنید؛ مثلاً 4-4. سپس:
usbipd bind --busid 4-4
یک پنجره Ubuntu باز نگه دارید و در PowerShell معمولی اجرا کنید:
usbipd attach --wsl --busid 4-4
در Ubuntu بررسی کنید:
lsusb
ls /dev/ttyACM* /dev/ttyUSB* 2>/dev/null
اگر برد هنگام Reset از WSL جدا شد، فرمان usbipd attach را دوباره اجرا کنید. پس از پایان کار نیز میتوانید بنویسید:
usbipd detach --busid 4-4
مرحله ۱: نصب پیشنیازها در Ubuntu یا WSL2
sudo apt update
sudo apt install -y git build-essential python3 python3-pip pipx curl unzip
کاربر را به گروه پورت سریال اضافه کنید:
sudo usermod -aG dialout "$USER"
برای اعمال عضویت گروه، یک بار از Ubuntu خارج و دوباره وارد شوید. در WSL میتوانید از PowerShell فرمان wsl --shutdown را اجرا کنید و سپس Ubuntu را باز کنید.
مرحله ۲: نصب Arduino CLI
روش رسمی مبتنی بر اسکریپت:
curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | sh
sudo install -m 0755 bin/arduino-cli /usr/local/bin/arduino-cli
arduino-cli version
اگر پوشه bin در مسیر دیگری ساخته شد، مسیر فایل خروجی اسکریپت را در دستور install جایگزین کنید.
تنظیم اولیه Arduino CLI:
arduino-cli config init
arduino-cli config add board_manager.additional_urls \
https://espressif.github.io/arduino-esp32/package_esp32_index.json
arduino-cli core update-index
arduino-cli core install esp32:esp32
بررسی نصب:
arduino-cli core list
باید پکیج esp32:esp32 در خروجی دیده شود.
مرحله ۳: نصب uv و Hugging Face CLI
نصب uv:
curl -LsSf https://astral.sh/uv/install.sh | sh
نصب فرمان hf:
pipx install huggingface-hub
pipx ensurepath
ترمینال را ببندید و دوباره باز کنید، سپس:
uv --version
hf --help
اگر hf پیدا نشد، موقتاً مسیر زیر را اضافه کنید:
export PATH="$HOME/.local/bin:$PATH"
برای این مدلهای عمومی معمولاً ورود به حساب Hugging Face لازم نیست.
مرحله ۴: دریافت پروژه esp32-ai
git clone https://github.com/slvDev/esp32-ai.git
cd esp32-ai
ساختار مهم پروژه:
esp32-ai/
├── firmware/
│ ├── esp32_barista/
│ └── esp32_tinystories/
├── runtime/
├── scripts/
│ ├── fetch_model.sh
│ └── deploy.sh
└── artifacts/ # پس از دانلود مدل ساخته میشود
مرحله ۵: بررسی پورت برد
برد را با کابل USB دادهدار متصل کنید:
arduino-cli board list
پورت در Linux و WSL معمولاً یکی از این موارد است:
/dev/ttyACM0
/dev/ttyUSB0
در macOS معمولاً پورت شبیه /dev/cu.usbmodem... است.
اگر هیچ پورتی مشاهده نشد:
- کابل را عوض کنید؛ بسیاری از کابلها فقط شارژ هستند.
- اتصال usbipd در WSL را بررسی کنید.
- دکمه BOOT را نگه دارید، یک بار RESET را فشار دهید و BOOT را رها کنید.
- خروجی
dmesg | tail -30را بررسی کنید.
مرحله ۶: دانلود مدل Barista
در ریشه مخزن اجرا کنید:
scripts/fetch_model.sh barista
این اسکریپت فایلهای زیر را از مخزن مدل دریافت میکند:
model.bintokenizer.jsonvocab.jsonlayout.jsonmetadata.json
فایلها ابتدا در مسیر موقت دانلود میشوند. اسکریپت اندازه و SHA-256 فایلها را با مقادیر ثابت داخل پروژه مقایسه میکند و فقط در صورت تأیید، آنها را در artifacts/barista/ قرار میدهد. بنابراین دانلود ناقص یا فایل دستکاریشده بهعنوان مدل معتبر نصب نمیشود.
بررسی دستی فایلها:
ls -lh artifacts/barista
مرحله ۷: کامپایل و فلش Barista
پورت خود را در فرمان قرار دهید:
PORT=/dev/ttyACM0 scripts/deploy.sh barista
اگر پورت /dev/ttyUSB0 بود:
PORT=/dev/ttyUSB0 scripts/deploy.sh barista
در macOS:
PORT=/dev/cu.usbmodemXXXX scripts/deploy.sh barista
اسکریپت deploy.sh این مراحل را خودکار انجام میدهد:
- جدول واژگان و هدرهای Tokenizer را از فایلهای همان مدل میسازد.
- سازگاری Tokenizer، جدول خروجی و مدل را روی رایانه بررسی میکند.
- تست مسیر محاسبات int8 را اجرا میکند.
- فریمور را با بهینهسازی
-O3و تنظیم ESP32-S3 N16R8 کامپایل میکند. - مدل را در پارتیشن سفارشی و از آدرس
0x110000مینویسد. - فریمور را آپلود میکند.
- fingerprint فایل فلششده را برای مقایسه با خروجی بوت چاپ میکند.
کامپایل قبل از فلش انجام میشود؛ بنابراین اگر Build شکست بخورد، مدل جدید روی فریمور قدیمی نوشته نخواهد شد.
اگر آپلود شروع نشد، دکمه BOOT را نگه دارید، یک بار RESET را بزنید و پس از شروع نوشتن BOOT را رها کنید.
مرحله ۸: باز کردن Serial Monitor
arduino-cli monitor -p /dev/ttyACM0 --config baudrate=115200

در راهاندازی صحیح باید خروجی نزدیک به این ببینید:
=== ESP32 BARISTA ===
ask an espresso question; the model writes the answer.
model: Vin=8057 Vout=854 D=128 L=6 H=4 F=384 P=128
scratch in SRAM: 20940 B
norms in SRAM: 20/20 vectors, 10656 B
sram free 288 KB
int8-staged 44 tensors | psram free 5.55 MB
config: profile=0 dual_core_requested=1 dual_core_active=1 ...
READY>
حالا سؤال انگلیسی مرتبط با اسپرسو وارد و Enter را فشار دهید:
Why is my espresso sour?
یا:
How fine should I grind coffee?
خروجی بهتدریج در Serial نمایش داده میشود. برای خروج از مانیتور، کلید میانبر نمایشدادهشده توسط Arduino CLI، معمولاً Ctrl+C، را بزنید. تا زمانی که Serial Monitor باز است، ابزار دیگری نمیتواند همان پورت را برای Upload استفاده کند.
مرحله ۹: اجرای TinyStories
برای نصب مدل داستانساز:
scripts/fetch_model.sh tinystories
PORT=/dev/ttyACM0 scripts/deploy.sh tinystories
سپس Serial Monitor را باز کنید:
arduino-cli monitor -p /dev/ttyACM0 --config baudrate=115200
Deploy کردن TinyStories، مدل Barista را جایگزین میکند. برای بازگشت به Barista کافی است دوباره scripts/deploy.sh barista را اجرا کنید؛ اگر فایلهای مدل هنوز در artifacts/barista هستند، نیازی به دانلود مجدد نیست.
اتصال OLED به ESP32-S3
OLED اجباری نیست و پیشنهاد میکنیم اولین تست را فقط با Serial انجام دهید. پس از اطمینان از اجرای مدل، نمایشگر I2C تکرنگ 128×64 را مطابق جدول متصل کنید.

| پایه OLED | پایه ESP32-S3 |
|---|---|
| GND | GND |
| VCC | 3V3 |
| SCL | GPIO46 |
| SDA | GPIO18 |
نکات مهم:
- نمایشگرهای ۱٫۳ اینچ معمولاً کنترلر SH1106 دارند.
- نمایشگرهای ۰٫۹۶ اینچ معمولاً SSD1306 هستند.
- آدرس پیشفرض پروژه
0x3Cاست؛ بعضی پنلها0x3Dهستند. - کنترلر پیشفرض Barista در کد SH1106 است.
- اتصال VCC به ۵ ولت را بدون بررسی دیتاشیت ماژول OLED انجام ندهید؛ 3V3 امنترین گزینه برای این اتصال است.
اگر OLED ندارید، پروژه فقط یک بار وجود نمایشگر را بررسی میکند و سپس خروجی Serial ادامه پیدا میکند. برای حذف کامل کد نمایشگر از Build میتوان USE_DISPLAY=0 را به فلگهای کامپایل اضافه کرد، اما اسکریپت آماده Deploy بهصورت پیشفرض نمایشگر را فعال نگه میدارد.
رفع خطاهای متداول
خطای missing: hf
pipx install huggingface-hub
pipx ensurepath
export PATH="$HOME/.local/bin:$PATH"
ترمینال را دوباره باز و hf --help را تست کنید.
خطای missing: arduino-cli
فایل Arduino CLI در PATH نیست. با which arduino-cli بررسی کنید و در صورت نیاز آن را به /usr/local/bin منتقل کنید.
خطای esptool not found
ابتدا نصب هسته ESP32 را بررسی کنید:
arduino-cli core list
در صورت نیاز:
python3 -m pip install --user esptool
خطای Permission denied برای پورت
sudo usermod -aG dialout "$USER"
سپس Session را کامل ببندید و دوباره وارد شوید. استفاده دائمی از sudo برای Arduino CLI توصیه نمیشود.
پورت پیدا نمیشود
lsusb
dmesg | tail -30
ls -l /dev/ttyACM* /dev/ttyUSB* 2>/dev/null
در WSL دوباره usbipd attach --wsl --busid ... را اجرا کنید.
پیام مربوط به کمبود PSRAM
این خطا معمولاً یعنی برد N16R8 نیست، PSRAM در تنظیمات درست انتخاب نشده یا حافظه برد معیوب است. نوشته روی ماژول و مشخصات فروشنده را بررسی کنید. اسکریپت پروژه خودش PSRAM=opi را تنظیم میکند.
خطای word table mismatch
فریمور یک مدل با فایل وزن مدل دیگر ترکیب شده است. مثال رایج، فریمور Barista روی پارتیشن TinyStories است. مدل صحیح را دوباره Deploy کنید:
PORT=/dev/ttyACM0 scripts/deploy.sh barista
خروجی OLED بههمریخته است
احتمالاً کنترلر نمایشگر اشتباه انتخاب شده است. برای OLED معمولی ۰٫۹۶ اینچ SSD1306 و برای بسیاری از مدلهای ۱٫۳ اینچ SH1106 را امتحان کنید. آدرس 0x3C و 0x3D را نیز با I2C Scanner بررسی کنید.
دانلود مدل ناقص یا Hash نامعتبر است
اسکریپت فایل نامعتبر را نصب نمیکند. اینترنت، فضای دیسک و ساعت سیستم را بررسی و فرمان fetch_model.sh را دوباره اجرا کنید. مقادیر Hash را دستی تغییر ندهید.
آیا میتوان مدل فارسی روی ESP32 اجرا کرد؟
از نظر پژوهشی میتوان مدل کوچک دیگری را آموزش، Quantize و برای Runtime پروژه Export کرد؛ اما صرفاً جایگزین کردن یک فایل مدل عمومی کافی نیست. مدل باید با معماری، چیدمان Tensorها، Tokenizer، اندازه واژگان و ابزار Export همین پروژه سازگار شود.
فارسی به Tokenizer مناسب و داده آموزشی فارسی نیاز دارد. افزایش واژگان نیز جدول embedding را بزرگ میکند و بهسرعت محدودیت Flash را تحت فشار قرار میدهد. بنابراین ساخت مدل فارسی روی این برد یک پروژه آموزش مدل و بهینهسازی حافظه است، نه یک تنظیم ساده در فریمور.
جمعبندی
پروژه esp32-ai نمونه جذابی از اجرای واقعی یک مدل زبانی کاملاً آفلاین روی میکروکنترلر است. بااینحال انتخاب سختافزار تعیینکننده است: ESP32-WROOM-32 معمولی برای نسخه آماده پروژه مناسب نیست و باید از ESP32-S3 N16R8 با ۱۶MB Flash و ۸MB PSRAM استفاده کنید.
برای شروع، مدل Barista را نصب کنید، خروجی را ابتدا در Serial Monitor ببینید و سپس OLED را اضافه کنید. TinyStories مدل بزرگتر و نمایشیتر پروژه است، اما هیچکدام را نباید با دستیارهای زبانی بزرگ مانند ChatGPT مقایسه کرد. نقطه قوت این پروژه، معماری حافظه و اجرای کاملاً محلی آن است.
سؤالات متداول
آیا LLM پروژه esp32-ai روی ESP32-WROOM-32 اجرا میشود؟
خیر. ESP32-WROOM-32 معمولاً ۴MB Flash و بدون PSRAM است؛ درحالیکه پروژه به ESP32-S3 با ۱۶MB Flash و ۸MB PSRAM نیاز دارد.
برای اجرای esp32-ai دقیقاً چه بردی بخریم؟
ESP32-S3-DevKitC-1 با ماژول ESP32-S3-WROOM-1-N16R8 انتخاب پیشنهادی است. عبارت N16R8 باید در مشخصات برد وجود داشته باشد.
آیا مدل برای اجرا به اینترنت نیاز دارد؟
خیر. اینترنت فقط یک بار برای دانلود سورس، ابزارها و فایل مدل لازم است. پس از فلش، استنتاج روی خود برد انجام میشود.
آیا این پروژه به API هوش مصنوعی وصل میشود؟
خیر. وزنها در Flash برد قرار دارند و محاسبات بهصورت محلی انجام میشوند.
تفاوت Barista و TinyStories چیست؟
Barista یک مدل کوچک پرسشوپاسخ درباره اسپرسو است و ورودی را از Serial میگیرد. TinyStories مدل بزرگتر داستانساز است که داستانهای ساده انگلیسی تولید میکند.
آیا نمایشگر OLED اجباری است؟
خیر. Serial همیشه فعال است و پروژه بدون OLED نیز اجرا میشود.
آیا میتوان روی این مدل فارسی صحبت کرد؟
مدلهای آماده برای فارسی آموزش ندیدهاند. ساخت نسخه فارسی به آموزش یا Fine-tune، Tokenizer سازگار، Quantization و Export مخصوص Runtime نیاز دارد.
چرا مدل فقط ۱۴٫۹MB است ولی ۲۸٫۹ میلیون پارامتر دارد؟
وزنها بهصورت ۴ بیتی ذخیره شدهاند و بخش بزرگی از پارامترها در جدول embedding داخل Flash باقی میمانند؛ فقط دادههای لازم در زمان اجرا خوانده میشوند.