میکروپایتون یک بازپیاده سازی از زبان برنامه نویسی پایتون است که برای میکروکنترلرها و امبدد سیستمهایی مانند ESP32 و ESP8266 است.
برنامه نویسی میکروپایتون خیلی شبیه به برنامه نویسی پایتون است. به جز تعدادی از استثناها، همه ویژگیهای پایتون در میکروپایتون هم هستند. چون میکروکنترلرها و امبدد سیستمها بسیار محدودتر از کامپیوترهای ما هستند، میکروپایتون به طور پیش فرض با کتابخانههای تمام استاندارد نمیآید.
اگر شما برنامه نویسی در پایتون را میدانید، برنامه نویسی در میکروپایتون هم همان است. شما فقط باید در نظر بگیرید که میکروپایتون برای دستگاه های محدود استفاده میشود پس کد شما تا حد امکان باید ساده باشد.
این مقاله اصول زبان برنامه نویسی پایتون را توضیح میدهد که برای میکروپایتون هم قابل اعمال است. مانند:
عملگرهای ریاضی
عملگرهای رابطهای
انواع داده
تابع print
عبارتهای شرطی
حلقههای for و while
توابعی که توسط کاربر تعریف میشوند
کلاسها و اشیا
ماژولها
پیشنیازها
در این آموزش ما از uPyCraft IDE به عنوان محیط توسعه استفاده میکنیم اما شما میتوانید از برنامههای دیگر هم استفاده کنید.
عملگرهای ریاضی
میکروپایتون میتواند عملهای ریاضی را انجام دهد. جدول زیر عملگرهای قابل استفاده را نشان میدهد.
عملگر | عملیات ریاضی |
+ | جمع |
_ | تفریق |
* | ضرب |
/ | تقسیم |
// | تقسیم بدون محاسبه اعشار |
% | باقیمانده تقسیم |
برای این که ببینید عملگرها چگونه کار میکنند، چند تا از آنها را در Shell امتحان کنید. برای مثال:
>>> 2+2*9-3
۱۷
>>> 28594/2312
۱۲.۳۶۷۶۵
>>> 214522236/7.5
۲.۸۶۰۲۹۷e+07
>>> 23//2
۱۱
>>> 25%3
۱
اگر شما ماژول math را وارد کنید، میتوانید سایر اعمال ریاضی مانند ریشه دوم، توابع مثلثاتی، لگاریتم، نمایی و… را استفاده کنید.
عملگرهای رابطهای
با استفاده از عملگرهای رابطهای شما میتوانید مقایسه انجام دهید. این عملگرها مقادیر دو طرف را با هم مقایسه میکنند و رابطه بین آنها را نشان میدهند.
عملگر | توضیح |
== | مساوی است با |
=! | مساوی نیست با |
< | بزرگتر |
> | کوچکتر |
=< | بزرگتر مساوی |
=> | کوچکتر مساوی |
سعی کنید چند مقایسه را انجام دهید و نتیجه را امتحان کنید:
>>> 2 == 3
False
>>> 4 == 4
True
>>> 3 > 2
True
>>> 489808234 != 2223
True
>>> 4.5 >= 4.5
True
اختصاص دادن مقادیر به متغیرها:
در پایتون نیازی نیست که نوع هر داده را مشخص کنید. اگر شما قبلا بردهای خود را با Arduino IDE پروگرم کرده باشید، میدانید که وقتی متغیر جدید تعریف میکنید، نیاز دارید که نوع آن را مشخص کنید. چنین چیزی در پایتون نیست.
متغیرها یک محل نگه داری برای مقادیر(اعداد یا متن) هستند. برای اختصاص یک مقدار به یک متغیر از علامت مساوی(=) استفاده میشود. نام متغیر در سمت چپ و و مقدار در سمت راست مساوی قرار میگیرند.
برای مثال، برای ایجاد یک متغیر برای نگه داری مقدار GPIO وقتی LED وصل است، میتوانید به صورت زیر بنویسید:
led_pin = 23
در Arduino IDE ، شما چیزی شبیه دستور زیر را دارید:
const int led_pin = 23;
همان طور که میبینید، برنامه نویسی در پایتون خیلی سادهتر از برنامه نویسی در C است. (در Arduino IDE)
توجه: نامهایی که به متغیرها میدهید نمیتوانند فاصله (space) داشته باشند و حساس به حروف کوچک و بزرگ هستند. بنابراین led_pin با LED_PIN یا Led_Pin فرق دارد.
انواع داده
متغیرها میتوانند نه تنها عددها، بلکه چندین نوع از مقادیر را در خود ذخیره کنند. این جاست که پای انواع داده به میان میآید. یک نوع داده، طبقه بندی مقادیر هست به گونهای که مشخص میکند چه عملیاتی با مقادیر میتوانند انجام شوند و یا مقادیر چگونه ذخیره میشوند.
جدول زیر انواع داده را نشان میدهد که ما اغلب در پروژهها استفاده میکنیم.
نوع داده | توضیح |
Int(Int) | عدد صحیح |
Float(Float) | عدد اعشاری |
str(string) | رشته |
Bool(Boolean) | بولین |
بیاید متغیرهایی با انواع مختلف داده تعریف کنیم:
>>> a = 6
>>> b = 95.32
>>> c = 'Hello World!'
>>> d = True
مقدار اول که به a اختصاص داد شده است، یک عدد صحیح است. (عددی کامل است.)
متغیر b شامل یک مقدار اعشاری است که یک عدد با اعشار است.
مقدار سوم ‘Hello World!’ یک رشته است که مجموعهای از کاراکترها میباشد. یک رشته باید داخل تک کوتیشن (‘Hello World!’) یا دابل کوتیشن (“Hello World!”) قرار داده شود.
d یک بولین است. نوعی داده است که میتواند True یا False باشد.
برای چک کردن نوع یک متغیر تابعی وجود دارد: تابع ()type. آرگومان این تابع، متغیری است که میخواهیم نوع آن را بدانیم.
type(variable)
در مثال قبلی، بعد از این که متغیرهای a,b,c,d تعریف شدند، میتوانیم نوع آن را مشخص کنیم. مثلا اگر بنویسید:
>>> type(a)
عبارت زیر نمایش داده میشود:
<class 'int'>
این عبارت به ما میگوید که a یک عدد صحیح است. برای سایر متغیرها نیز نتایج زیر به دست میآید:
>>> type(b)
<class 'float'>
>>> type(c)
<class 'str'>
>>> type(d)
<class 'bool'>
تابع ()print
تابع print عبارت بین دو پرانتز را در صفحه shell چاپ میکند و در پروژهها برای دیباگ کردن کد کارآمد است چون میتوانیم اجرای کد را دنبال کنیم. مثلا:
>>> print('LED is on')
LED is on
کامنتها
کامنتها یا توضیحات در پایتون با کاراکتر # شروع میشوند و تا آخر خط ادامه دارند. یک کامنت برای اضافه کردن یادداشت به برنامه به کار میرود و یا به کسی که برنامه را میخواند میگوید که هر تکه از کد نوشته شده چه کاری انجام میدهد. کامنتها هیچ تابعی را به برنامه شما اضافه نمیکنند. برای مثال:
# This is just a comment
چون ما از میکروپایتون در شرایط محدود شده استفاده میکنیم، گاهی اوقات شما مجبورید برای ذخیره فضا در حافظه ESP، از کامنتگذاری پرهیز کنید.
عبارتهای شرطی
برای نوشتن یک برنامه کارآمد، احتمالا شما بر اساس این که یک عبارت درست هست یا غلط (True or False) کارهای متفاوتی را انجام میدهید. ما دربارهی عبارتهای شرطی صحبت میکنیم. ساختار آنها به شکل زیر است:
if <expr1>:
<statement1>
elif <expr2>:
<statement2>
elif <expr3>:
<statement3>
(...)
else:
<statementn>
<expr>یک عبارت بولین است که میتواند درست یا غلط باشد. <statement>باید نسبت به <expr> با فاصله بیشتری از ابتدای خط قرار بگیرد تا پایتون بفهمد که کدام حکم به کدام شرط مربوط است.
عبارت elif مخفف else if است و فقط اگر اولین شرط (اولین if) برقرار نباشد، اجرا میشود.
عبارت else نیز فقط زمانی اجرا میشود که عبارتهای شرطی برقرار نباشند.
هیچ محدودیتی برای تعداد elif در برنامه وجود ندارد. همچنین لزومی ندارد که شرط حتما شامل else باشد اما اگر else داشتیم، حتما باید در انتهای شرطها آورده شود.
در Arduino IDE از علامتهای {} برای بلوک کد استفاده میکنیم ولی در میکروپایتون از ایجاد فرورفتگی در ابتدای خط استفاده میکنیم و بعد از هر عبارت شرطی باید علامت : (colon) قرار دهیم و برخلاف Arduino IDE نیازی نیست که عبارات داخل پرانتز باشند.
توجه مهم: مقدار فرورفتگی در پایتون به اندازه ۴ فاصله (space) است. در میکروپایتون فرورفتگیها باید به اندازه ۲ فاصله (space) باشد تا کد بیشتری در حافظه میکروکنترلر جا بگیرد.
حلقههای for و while
حلقهها به شما اجازه میدهند تا یک بلوک از کد به تعدادی که برای آن مشخص کردید، اجرا شوند. دو نوع حلقه داریم: حلقه for و حلقه while . برای مثال شما میتوانید تمام اعداد بین ۱ تا ۱۰ را با استفاده از حلقه while چاپ کنید.
number = 1
while number <= 10:
print(number)
number = number + 1
کدی که به حلقه while مربوط است، با ایجاد فرورفتگی از ابتدای خط مشخص شده است و تا زمانی که مقدار متغیر number کوچکتر و مساوی ۱۰ باشد، اجرا میشود. در هر حلقه، مقدار فعلی متغیر number چاپ میشود و سپس یکی به مقدار آن اضافه میشود.
شما میتوانید اعداد ۱ تا ۱۰ را با حلقه for هم چاپ کنید:
number = 1
for number in range(1, 11):
print(number)
حلقه for به تعدادی که مقدار متغیر number در محدودهی ۱ تا ۱۱ باشد، اجرا میشود. تابع range تا زمانی که مقدار متغیر number یکی کمتر از مقدار آخری که مشخص کردید (۱۱) باشد، به طور اتوماتیک مقدار بعدی را به متغیر number اختصاص میدهد.
وقتی بخواهیم یک بلوک از کد به تعداد دفعات مشخصی اجرا شود، از حلقه for استفاده میکنیم و از حلقه whie زمانی استفاده میکنیم که بخواهیم یک قطعه کد تا زمانی که یک شرط برقرار است، اجرا شود. در بعضی موارد میتوان از هر دو حلقه استفاده کرد ولی معمولا یکی بر دیگری ترجیح دارد.
مشابه عبارتهای شرطی، دقیقا بعد از عبارتهای بولین حلقههای for و while علامت : (colon) قرار میگیرد و کدی که باید اجرا شود، در ابتدای خط فرورفتگی دارد.
توابعی که توسط کاربر تعریف میشوند
برای تعریف یک تایع جدید، از کلمه def به همراه نامی که برای تابع انتخاب شده است و پرانتز استفاده میکنیم. (تابع میتواند آرگومان داشته باشد یا نداشته باشد.) بعد از پرانتز باید علامت : (colon) و سپس دستوری که قرار است اجرا شود، قرار بگیرند. دقت کنید که فرورفتگی باید به اندازه ۲ فاصله (space) باشد. (در میکروپایتون):
def my_function(<arg1>, <arg2>, ...):
<statement>
(...)
return
برای مثال، یک تابعی که دما را سلسیوس به فارنهایت تبدیل میکند، به صورت زیر تعریف میشود:
def celsius_to_fahrenheit(temp_celsius):
temp_fahrenheit = temp_celsius * (9/5) + 32
return temp_fahrenheit
آرگومان تابع () celsius_to_fahrenheit دما برحسب سلسیوس (temp_celsius) است. محاسبات تبدیل دما انجام میشود و در نهایت دما بر حسب فارنهایت (temp_fahrenheit) برگردانده میشود.
توجه: نیازی نیست که تابع حتما چیزی را برگرداند. آنها میتوانند کاری را انجام دهند بدون این که چیزی برگردانند.
کلاسها و اشیا
پایتون یک زبان برنامه نویسی شی گرا است. دو مفهوم مهم در شی گرایی، کلاسها و اشیا هستند. کلاسها دستورالعملی برای اشیا هستند و به صورت ویژگیهایی هایی (توابع و دادهها) که شی را توصیف میکنند، تعریف میشوند. توابع داخل کلاس، «متد» نامیده میشوند. کلاسها توسط کلمه کلیدی class و نامی که برای آن انتخاب میکنیم، تعریف میشوند. برای مثال:
class MyClass:
(...)
توجه: به صورت قراردادی، اسامی کلاسها در پایتون به صورت CapWords است. هر چند که شما میتوانید هر اسمی را برای کلاس انتخاب کنید.
یک شی مثالی از یک کلاس و مجموعهای از دادهها و متدهاست. در یک شی شما میتوانید از تمام ویژگیهای کلاس آن استفاده کنید. گیجکننده به نظر میرسد اما به مثال ساده زیر توجه کنید:
اگر بخواهیم چند شخص با ویژگیهای یکسان را در برنامه پایتون تعریف کنیم، اشخاص را میتوانیم کلاسها در نظر بگیریم. ممکن است بخواهیم شخصی را با ویژگیهایی مانند نام، سن، کشور و … تعریف کنیم.

پس میتوانیم کلاسی با نام person تعریف کنیم. این کلاس ویژگیهای نام، سن و کشور را دارد. شما میتوانید هر ویژگی را به این کلاس اضافه کنید. همچنین یک تابع (متد) میسازیم که هر شخص را طبق همان ویژگیها توصیف کند:
class Person:
name = ""
age = 0
country = ""
def description(self):
print("%s is %d years old and he is from %s." %(self.name, self.age, self.country))
همان طور که میبینید، یک کلاس جدید را با کلمه کلیدی class ایجاد کردیم و نامی که میخواستیم (person) را به آن دادیم.
داخل کلاس person ما چند متغیر تعریف کردیم که مقادیر را در آنها نگه داریم. به طور پیش فرض متغیرهای name و country رشتههای خالی هستند و مقدار اولیه age نیز ۰ است. سپس ما تابعی (متد) تعریف کردیم که مقادیر متغیرها را درصفحه Shell چاپ کند.
تمام توابع داخل کلاس باید پارامتر self را در آرگومان خود به همراه سایر آرگومانها (اگر نیاز بود) داشته باشند.
پارامتر self به شی اشاره دارد و برای دسترسی به متغیرهایی که به کلاس تعلق دارند، استفاده میشود. برای مثال برای دسترسی به متغیر name در کلاس، از self.name استفاده میشود.
حالا که ما کلاس را ساختهایم میتوانیم تعداد زیادی شی با عنوان person را ایجاد کنیم. شی person، یک نام، سن و کشور را خواهد داشت. همچنین ما میتوانیم توصیفات شخص را با متد () description چاپ کنیم.
برای مثال، برای یک شخصی که person1 نام دارد، خواهیم داشت:
>>> person1 = Person()
مشخص کردن ویژگیهای شی
برای مشخص کردن نام، سن و کشور شی person1 مانند زیر عمل میکنیم:
>>> person1.name = "Rui"
>>> person1.age = 25
>>> person1.country = "Portugal"
فراخوانی متدها
شما میتوانید برای شی person از متد ساخته شده () description استفاده کنید. برای فراخوانی تابع ()description برای شی person1 میتوانیم بنویسیم:
>>> person1.description()
در نتیجه عبارت زیر چاپ میشود:
Rui is 25 years old and he is from Portugal.
باید تا الان متوجه شده باشید که میتوانیم اشیا زیادی را با استفاده از کلاس بسازیم و میتوانیم متدهای در دسترس را با تمام اشیا کلاس استفاده کنیم.

متد سازنده
به جای تعریف کلاس و سپس مشخص کردن ویژگیهای شی که زمانبر است، میتوانید از متد سازنده در داخل کلاس خود استفاده کنید. از متد سازنده برای شروع دادهها به محض ایجاد یک شیء از کلاس استفاده میشود. متد سازنده به صورت __init__ است. با استفاده از متد __init__، کلاس ()Person به شکل زیر نوشته میشود:
class Person():
def __init__(self, name, age, country):
self.name = name
self.age = age
self.country = country
def description(self):
print("%s is %d years old and he is from %s." %(self.name, self.age, self.country))
برای نمونه، شی Person با همان ویژگیهایی که بالاتر تعریف کردیم، به صورت زیر در میآید:
>>> person1 = Person("Rui", 25, "Portugal")
اگر شما تابع () description را برای شی person1 فراخوانی کنید، همان نتیجه قبل را خواهد داشت:
>>> person1.description()
Rui is 25 years old and he is from Portugal.
ماژولها
یک ماژول فایلی شامل مجموعهای از کلاسها و توابع است که شما میتوانید در کدتان استفاده کنید. میتوان آنها را کتابخانه نیز نامید. برای دسترسی به کلاسها و توابع در داخل کد، شما نیاز دارید که آن ماژول را به کدتان وارد کنید. (import)
شما میتوانید ماژول خودتان را بسازید یا از ماژولهایی که از کتابخانههای استاندارد پایتون که ایجاد شدهاند استفاده کنید. در میکروپایتون، از زیرمجموعهای کوچک از کتابخانههای استاندارد پایتون برای کنترل GPIOها، ارتباط شبکهها و… استفاده میشود.
وارد کردن ماژولها (کتابخانهها) به صورت زیر است:
import module_name
برای مثال، برای وارد کردن کتابخانه machine که شامل کلاسهایی برای کنترل GPOIها است، نوشته میشود:
import machine
در بیشتر برنامهها شما نیاز ندارید که تمام کلاسهای یک ماژول را استفاده کنید و ممکن است که فقط یک کلاس آن را احتیاج داشته باشید. برای مثال، برای وارد کردن کلاس Pin از ماژول machine داریم:
from machine import Pin

جمعبندی
در این آموزش، ما اصول اولیه پایتون برای استفاده در میکروپایتون را بررسی اجمالی کردیم. اگر شما از Arduino IDE برای پروگرم کردن استفاده کرده باشید، متوجه شدید که میکروپایتون بسیار سادهتر و کاربرپسندتر است. بعضی تفاوتهای اصلی بین Arduino و میکروپایتون عبارتاند از:
- در میکروپایتون نیازی نیست که انتهای عبارتها علامت ; (semicolon) گذاشته شود.
- در میکروپایتون بعد از عبارتهای بولین در گزارههای شرطی و حلقهها علامت : (colon) میآید.
- در میکروپایتون برای تعریف بلوک کد به جای آکلاد از فرورفتگی از ابتدای خط استفاده میشود.
- در میکروپایتون وقتی متغیری تعریف میکنید، نیازی نیست که نوع آن را مشخص کنید.
- در میکروپایتون فرورفتگی از ابتدای خط به اندازه ۲ فاصله (space) است.