🐍 آموزش میکروپایتون از صفر: متغیر، شرط، حلقه، تابع، لیست و کار با پایههای برد
اگر دنبال یک آموزش میکروپایتون هستی که از صفر شروع کند و آخرش بتوانی یک LED و دکمه را با کد خودت کنترل کنی، این صفحه برای توست. میکروپایتون (MicroPython) همان پایتون ۳ است که آنقدر کوچک شده که روی یک میکروکنترلر ارزان مثل رزبری پای پیکو یا ESP32 جا شود. نه کامپایل لازم دارد و نه نصب پیچیده؛ مینویسی، اجرا میکنی و نتیجه را بلافاصله میبینی. در این درس قدمبهقدم متغیر، نوع داده، شرط، حلقه، تابع، لیست، مدیریت خطا، ماژولها و در آخر کار با پایههای برد را یاد میگیری؛ هر بخش با یک کد کوتاه که میتوانی همین حالا اجرایش کنی.
این آموزش را چطور بخوانی؟
هر بخش یک مفهوم است و یک مثال کوچک. توصیهی ما این است که فقط نخوانی: هر کد را اجرا کن، یک عددش را عوض کن و ببین چه اتفاقی میافتد. برای اجرا دو راه داری:
- شبیهساز، بدون خرید برد: در تینکرکد فارسی یک پیکوی مجازی برمیداری و کد را در ادیتور مینویسی. خروجی
printدر «سریال مانیتور» دیده میشود. شبیهساز در مرورگر و روی گوشی کار میکند و روی اینترنت ملی هم باز میشود. پیکو و میکروپایتون جزو امکانات اشتراک پلاس هستند؛ مثالهای آماده برای خواندن رایگاناند و برای اجرا پلاس لازم داری. - برد واقعی: فرمور میکروپایتون را روی پیکو بریز و با نرمافزار Thonny کد را اجرا کن. راهنمای کاملش در نصب میکروپایتون روی پیکو و Thonny است.
import (مثل import time) شروع میشوند. روی برد واقعی این خط برای مثالهای ساده اجباری نیست، ولی در شبیهساز کمک میکند ادیتور بفهمد برنامهی تو میکروپایتون است، نه ++C آردوینو.۱. اولین برنامه: print
تابع print هر چیزی را که به آن بدهی چاپ میکند. روی میکروکنترلر، خروجی آن به سریال مانیتور (یا پنجرهی Shell در Thonny) میرود و مهمترین ابزار تو برای فهمیدن این است که برنامه کجاست و چه میکند.
import time
print("Salam, MicroPython!")
print(2 + 3)
print("2 + 3 =", 2 + 3)
وقتی چند چیز را با کاما جدا میکنی، print بینشان یک فاصله میگذارد. متن باید بین دو علامت نقلقول باشد؛ "..." یا '...' فرقی ندارد.
۲. متغیرها و نوع دادهها
متغیر یک اسم است برای یک مقدار؛ مثل برچسبی که روی یک جعبه میچسبانی. در پایتون لازم نیست نوع متغیر را از قبل بگویی (برخلاف int x; در آردوینو)؛ خود زبان از روی مقدار میفهمد.
import time
name = "Sara" # str : text
age = 13 # int : whole number
height = 1.52 # float : decimal number
likes_robots = True # bool : True or False
print(name, age, height, likes_robots)
print(type(age), type(height))
age = age + 1
print("Next year:", age)
print(7 / 2) # 3.5 normal division
print(7 // 2) # 3 integer division
print(7 % 2) # 1 remainder
text = "42"
number = int(text) # str -> int
print(number * 2) # 84
print("Age: " + str(age)) # int -> str
print(f"{name} is {age} years old")
- چهار نوع اصلی:
intعدد صحیح،floatعدد اعشاری،strمتن وboolدرست/غلط. تابعtype()نوع هر مقدار را نشان میدهد. - تقسیم:
/همیشه جواب اعشاری میدهد و//قسمت صحیح را. در کار با سنسورها هر دو را زیاد میبینی.%باقیمانده است و برای «هر چند بار یک بار» عالی است. - تبدیل نوع:
int("42")متن را عدد میکند وstr(13)عدد را متن. نمیتوانی متن و عدد را مستقیم با+به هم بچسبانی؛ اول باید تبدیل کنی. - f-string: وقتی جلوی متن حرف
fبگذاری، هر چیزی بین آکولاد با مقدارش جایگزین میشود. خواناترین راه برای چاپ عدد کنار متن است. - اسم متغیر: با حرف شروع میشود، فاصله ندارد و به بزرگی و کوچکی حروف حساس است:
Ageوageدو متغیر جدا هستند.
۳. شرط: if، elif و else
برنامهها باید تصمیم بگیرند: اگر هوا گرم است پنکه روشن شود، اگر دکمه فشار داده شد چراغ عوض شود. این کار با if انجام میشود.
import time
temp = 31
if temp > 30:
print("Hot! Fan ON")
elif temp > 20:
print("Nice weather")
else:
print("Cold")
light = 150
is_night = light < 200
if is_night and temp < 35:
print("Night lamp ON")
if not is_night:
print("It is day")
- دونقطه و تورفتگی: آخر خط
ifدونقطه میآید و خطهای داخلش چهار فاصله جلوتر نوشته میشوند. همین تورفتگی است که میگوید کدام خطها جزو شرطاند؛ آکولاد نداریم. - مقایسه:
==برابر،!=نابرابر،<و>کوچکتر و بزرگتر،<=و>=. حواست باشد=یعنی «مقدار بده» و==یعنی «مقایسه کن». - ترکیب شرطها: در پایتون به جای
&&و||و!آردوینو، کلمههایand،orوnotرا مینویسی. - elif: کوتاهشدهی else if است. شرطها به ترتیب بررسی میشوند و اولین شرط درست اجرا میشود، بقیه نه.
۴. حلقهها: for و while
حلقه یعنی «این کار را چند بار تکرار کن». for وقتی است که تعداد تکرار را میدانی، و while وقتی که تا برقرار بودن یک شرط ادامه میدهی.
import time
for i in range(5):
print("i =", i) # 0 1 2 3 4
for i in range(10, 0, -2):
print(i) # 10 8 6 4 2
count = 3
while count > 0:
print("Countdown:", count)
count -= 1
time.sleep(1)
print("Go!")
n = 0
while True:
n += 1
if n % 2 == 0:
continue # skip even numbers
if n > 9:
break # leave the loop
print("odd:", n)
range(5)یعنی ۰ تا ۴؛ عدد آخر جزوش نیست.range(10, 0, -2)یعنی از ۱۰ شروع کن، تا قبل از ۰ برو و هر بار ۲ تا کم کن.count -= 1کوتاهشدهیcount = count - 1است.+=و*=هم داریم، ولی++آردوینو در پایتون وجود ندارد.while Trueحلقهی بیپایان است؛ همان کاری که تابعloop()در آردوینو میکند. تقریباً هر برنامهی میکروکنترلر یکی دارد.breakاز حلقه بیرون میپرد وcontinueبقیهی همین دور را رها میکند و میرود سراغ دور بعد.
۵. تابع: کد را یک بار بنویس، بارها صدا بزن
وقتی یک تکه کد را چند جا لازم داری، آن را در یک تابع میگذاری و به آن اسم میدهی. تابع میتواند ورودی (پارامتر) بگیرد و با return جواب برگرداند.
import time
def square(x):
return x * x
def greet(name, times=1):
for i in range(times):
print("Salam", name)
def c_to_f(c):
return c * 9 / 5 + 32
print(square(4)) # 16
greet("Ali") # times = 1 (default)
greet("Mina", 3)
for c in [0, 25, 100]:
print(c, "C =", c_to_f(c), "F")
score = 0
def add_point():
global score # change the variable outside the function
score += 1
add_point()
add_point()
print("score:", score) # 2
defتابع را تعریف میکند. تا وقتی صدایش نزنی، هیچ کاری نمیکند.times=1یک مقدار پیشفرض است: اگر هنگام صدا زدن چیزی ندهی، همین ۱ استفاده میشود.returnجواب را برمیگرداند و تابع همانجا تمام میشود. تابعی کهreturnندارد، مقدارNoneبرمیگرداند.- global: متغیری که بیرون تابع ساخته شده را داخل تابع فقط میشود خواند. برای تغییر دادنش باید اول تابع بنویسی
global score، وگرنه خطایNameErrorیاUnboundLocalErrorمیگیری. در کار با وقفهی دکمه زیاد به این برمیخوری.
۶. لیست، تاپل و دیکشنری
لیست چند مقدار را پشت سر هم در یک متغیر نگه میدارد؛ مثلاً شمارهی پایههای چند LED یا ده خوانش آخر یک سنسور. همان آرایهی آردوینو است، با این فرق که میتواند بزرگ و کوچک شود.
import time
pins = [15, 14, 13]
notes = ["do", "re", "mi"]
print(pins[0]) # 15 (first item, index 0)
print(pins[-1]) # 13 (last item)
print(len(pins)) # 3
pins.append(12)
print(pins) # [15, 14, 13, 12]
print(pins[1:3]) # [14, 13]
for note in notes:
print("Play", note)
for i, note in enumerate(notes):
print(i, note)
readings = [512, 498, 530, 505]
avg = sum(readings) / len(readings)
print("average:", avg, "max:", max(readings))
color = (255, 0, 0) # tuple: cannot be changed
ages = {"Ali": 12, "Sara": 13} # dict: key -> value
print(ages["Sara"]) # 13
- شمارهی خانهها (index) از صفر شروع میشود.
-1یعنی آخرین خانه. appendیک مقدار به ته لیست اضافه میکند وlenتعداد خانهها را میدهد.pins[1:3]یک برش است: از خانهی ۱ تا قبل از خانهی ۳.for note in notesمستقیم روی خود مقدارها حرکت میکند وenumerateشمارهی هر خانه را هم کنارش میدهد.sum،maxوminبرای میانگینگیری از خوانش سنسورها خیلی به کار میآیند.- تاپل (با پرانتز) مثل لیست است ولی عوض نمیشود؛ رنگهای نئوپیکسل را معمولاً با تاپل میدهند. دیکشنری (با آکولاد) هر مقدار را با یک «کلید» نگه میدارد، مثل یک دفترچهی تلفن.
۷. مدیریت خطا: try و except
وقتی چیزی خراب میشود (مثلاً کاربر به جای عدد حرف تایپ میکند)، پایتون یک «استثنا» پرتاب میکند و اگر کسی آن را نگیرد، برنامه میایستد. با try میگویی «این را امتحان کن» و با except میگویی «اگر این خطا آمد، به جای توقف این کار را بکن».
import time
text = "12a"
try:
n = int(text)
print("number:", n)
except ValueError:
print("Not a number:", text)
def safe_divide(a, b):
try:
return a / b
except ZeroDivisionError:
print("Cannot divide by zero")
return 0
print(safe_divide(10, 2)) # 5.0
print(safe_divide(1, 0)) # message, then 0
چند خطایی که در شروع زیاد میبینی و معنیشان:
| پیام خطا | یعنی چه؟ |
|---|---|
IndentationError | تورفتگی خطها یکسان نیست یا Tab و Space قاطی شده. |
SyntaxError | دونقطهی آخر if/for/def جا افتاده، یا پرانتز و نقلقول بسته نشده. |
NameError | اسمی را صدا زدهای که تعریف نشده؛ معمولاً غلط تایپی یا import جاافتاده. |
TypeError | دو نوع ناجور را با هم قاطی کردهای، مثلاً "Age: " + 13. |
ValueError | نوع درست است ولی مقدار نه، مثل int("12a"). |
در صفحهی گفتوگو با input() در میکروپایتون همین try/except را در عمل میبینی: برنامه از سریال مانیتور عدد میپرسد و اگر حرف تایپ کنی، به جای خراب شدن دوباره میپرسد.
۸. ماژولها و import؛ و ماژول time
میکروپایتون همهی ابزارهایش را یکجا بار نمیکند تا حافظه هدر نرود. هر چه لازم داری با import میآوری. سه شکل رایج:
import time: بعد مینویسیtime.sleep(1).from machine import Pin, ADC: فقط همینها را میآورد و مینویسیPin(15).import machine: بعد مینویسیmachine.Pin(15).
دو ماژولی که تقریباً در هر برنامهی سختافزاری میبینی time و machine هستند. اول time:
import time
start = time.ticks_ms()
time.sleep(0.5) # seconds (a float is fine)
time.sleep_ms(250) # milliseconds
time.sleep_us(100) # microseconds
elapsed = time.ticks_diff(time.ticks_ms(), start)
print("elapsed ms:", elapsed) # about 750
time.sleepبر حسب ثانیه است؛ برای میلیثانیهsleep_msرا به کار ببر. این مهمترین فرق ظاهری باdelay()آردوینوست.ticks_msزمان گذشته از روشن شدن برد را میدهد، مثلmillis(). برای کم کردن دو زمان همیشهticks_diffرا به کار ببر، چون شمارنده بعد از مدتی از صفر شروع میکند و تفریق ساده آن موقع جواب غلط میدهد.- با
ticks_msمیشود چند کار را بدونsleepهمزمان انجام داد؛ راه حرفهایترش تایمر است که در تایمر در میکروپایتون آمده.
۹. machine.Pin: حرف زدن با پایههای برد
اینجاست که پایتون به الکترونیک وصل میشود. کلاس Pin از ماژول machine یک پایهی برد را نشان میدهد. یک LED با مقاومت ۲۲۰ اهم به GP15 و یک دکمه بین GP14 و GND وصل کن:
from machine import Pin
import time
led = Pin(15, Pin.OUT)
button = Pin(14, Pin.IN, Pin.PULL_UP)
led.on()
time.sleep(1)
led.off()
led.value(1) # same as led.on()
led.toggle() # flip: on -> off
while True:
if button.value() == 0: # PULL_UP: pressed = 0
led.on()
else:
led.off()
time.sleep_ms(20)
Pin(15, Pin.OUT): پایهی GP15 خروجی است. عدد، شمارهی GP است، نه شمارهی فیزیکی پایه؛ نقشهی کامل در پین اوت رزبری پای پیکو آمده.Pin.IN, Pin.PULL_UP: ورودی با مقاومت بالاکش داخلی. دکمهی آزاد ۱ میخواند و دکمهی فشرده ۰.value()بدون ورودی پایه را میخواند و با ورودی آن را مینویسد.on،offوtoggleمیانبُرهای خواناتری هستند.- LED روی خود برد هم یک پایه است:
Pin("LED", Pin.OUT).
۱۰. همه با هم: چراغ مورس با دکمه
حالا همهی چیزهایی که یاد گرفتی را در یک برنامهی واقعی کنار هم میگذاریم: دیکشنری برای جدول مورس، تابع برای چشمک کوتاه و بلند، حلقه روی حروف، شرط برای دکمه و try/except برای توقف تمیز. با هر بار فشار دکمه، LED پیام SOS را مورس میزند.
from machine import Pin
import time
led = Pin(15, Pin.OUT)
button = Pin(14, Pin.IN, Pin.PULL_UP)
# dot = short flash, dash = long flash
MORSE = {"S": "...", "O": "---", "A": ".-", "B": "-..."}
UNIT_MS = 150
def flash(symbol):
led.on()
if symbol == ".":
time.sleep_ms(UNIT_MS)
else:
time.sleep_ms(UNIT_MS * 3)
led.off()
time.sleep_ms(UNIT_MS)
def send(word):
for letter in word:
code = MORSE.get(letter, "")
print(letter, code)
for symbol in code:
flash(symbol)
time.sleep_ms(UNIT_MS * 2) # gap between letters
presses = 0
try:
while True:
if button.value() == 0:
presses += 1
print("press", presses)
send("SOS")
time.sleep_ms(20)
except KeyboardInterrupt:
led.off()
print("stopped")
MORSE.get(letter, "") اگر حرفی در جدول نباشد، به جای خطا یک متن خالی برمیگرداند. KeyboardInterrupt خطایی است که روی برد واقعی با Ctrl+C یا دکمهی Stop در Thonny ایجاد میشود؛ گرفتنش باعث میشود LED روشن نماند. برای تمرین، حروف بیشتری به جدول اضافه کن و اسم خودت را مورس بزن.
میکروپایتون با پایتون معمولی چه فرقی دارد؟
- حافظه: پیکو حدود ۲۶۴ کیلوبایت RAM دارد، نه چند گیگابایت. لیستهای خیلی بزرگ نساز و رشتهها را در حلقهی سریع بیدلیل نچسبان.
- کتابخانهها:
pipو numpy و pandas نداری. به جایش ماژولهای سختافزاریmachine،neopixelو درایورهای کوچکی مثلssd1306هست که یک فایل.pyروی برد هستند. - سرعت: پایتون مفسری است و از ++C کندتر؛ برای LED و سنسور کاملاً کافی است، ولی کارهای خیلی سریع را به سختافزار (PWM، وقفه، تایمر) بسپار.
- REPL: روی برد واقعی میتوانی دستورها را یکییکی تایپ کنی و جواب بگیری؛ عالی برای امتحان سریع. مقایسهی کامل با زبان آردوینو در میکروپایتون یا C++ آردوینو؟ آمده.
اجرا در شبیهساز
سادهترین شروع، مثال آمادهی چشمکزن با MicroPython روی پیکو است. کد را پاک کن، هر کدام از مثالهای بالا را جایش بگذار و اجرا کن؛ خروجیها در سریال مانیتور میآیند. برای بخش ۹ و ۱۰ یک LED، یک مقاومت و یک دکمه به مدار اضافه کن و روی دکمهی مجازی کلیک کن. اگر هنوز مطمئن نیستی، مقالهی میکروپایتون روی رزبری پای پیکو هم یک معرفی کوتاه دارد. برای آشنایی با محیط اجرای آنلاین هم صفحهی میکروپایتون را ببین.
اشکالهای رایج مبتدیها
- قاطی کردن = و ==: در
if x = 5:پایتون خطای SyntaxError میدهد. برای مقایسه دو مساوی لازم است. - فراموش کردن دونقطه: آخر هر
if،elif،else،for،while،defوtryدونقطه میآید. - sleep با عدد میلیثانیه:
time.sleep(500)یعنی ۵۰۰ ثانیه، نه نیم ثانیه! بنویسtime.sleep(0.5)یاtime.sleep_ms(500). - چسباندن عدد به متن:
"T=" + 25خطا میدهد؛str(25)یا f-string به کار ببر. - حلقهی بیپایان بدون مکث: یک
while Trueخالی پردازنده را صددرصد مشغول میکند و روی برد واقعی گاهی Thonny را هم کند میکند. یکsleep_msکوچک داخلش بگذار. - شمارهی پایهی اشتباه:
Pin(15)یعنی GP15 که پایهی فیزیکی ۲۰ است، نه پایهی پانزدهم.
قدم بعدی
حالا که زبان را بلدی، وقت ساختن است. به این ترتیب جلو برو: اولین چشمکزن روی پیکو، دکمه و وقفه، PWM و LED نفسکش و خواندن پتانسیومتر با ADC. همهی آموزشهای این برد در بخش رزبری پای پیکو جمع شدهاند.
مثال input() و try/except را باز کن 🐍سؤالهای رایج
برای یادگیری میکروپایتون باید اول پایتون بلد باشم؟
نه. میکروپایتون خودش پایتون ۳ است، فقط کوچکتر. همین صفحه هر چیزی را که برای شروع لازم داری، از متغیر تا تابع و لیست، از صفر توضیح میدهد. اگر پایتون بلدی، فقط بخش machine و time برایت تازه است.
فرق میکروپایتون با پایتون معمولی چیست؟
زبان یکی است، ولی میکروپایتون برای حافظهی چندصدکیلوبایتی ساخته شده: pip و کتابخانههای بزرگی مثل numpy ندارد، و به جایش ماژول machine را دارد که با پایهها، PWM، ADC و I2C حرف میزند. ماژول time هم sleep_ms و ticks_ms اضافه دارد.
بدون برد واقعی میشود میکروپایتون تمرین کرد؟
بله. در شبیهساز فارسی تینکرکد یک رزبری پای پیکوی مجازی با میکروپایتون واقعی اجرا میشود و LED، دکمه، پتانسیومتر و سریال مانیتور دارد. اجرای پیکو و میکروپایتون به اشتراک پلاس نیاز دارد و مثالهای آماده برای خواندن رایگان باز میشوند.
چرا خطای IndentationError میگیرم؟
پایتون بلوکها را با فاصلهی اول خط میشناسد، نه با آکولاد. همهی خطهای داخل یک if، for، while یا def باید دقیقاً به یک اندازه (معمولاً چهار فاصله) جلو رفته باشند و Tab و Space را با هم قاطی نکنی.
مقالههای مرتبط
پین اوت رزبری پای پیکو: نقشهی کامل ۴۰ پایه، GP، ADC، I2C، SPI، UART و تغذیه
PWM با میکروپایتون روی رزبری پای پیکو: LED نفسکش با duty_u16 و freq
ADC رزبری پای پیکو با میکروپایتون: خواندن پتانسیومتر با read_u16 و تبدیل به ولتاژ
نمایشگر LCD کاراکتری ۱۶×۲ با ماژول I2C در آردوینو
همهی آموزشهای رزبری پای پیکو و میکروپایتون ← · همهی مقالهها